LLVM IR格式的基本介绍

2023-11-10

LLVM IR以两种格式存储在磁盘上:

1.位码(.bc文件)

2.汇编文本(.ll文件)

    以sum.c源代码为例

int sum(int a, int b){
  return a+b;
}

使用Clang生成位码,命令如下:

$ clang sum.c -emit-llvm -c -o sum.bc

使用Clang生成汇编文本,命令如下:

$ clang sum.c -emit-llvm -S -c -o sum.ll
$ clang -emit-llvm sum.c -S -o sum.ll

还可以汇编上述的LLVM IR汇编文本,创建相应的位码,命令如下:

$ llvm-as sum.ll -o sum.bc

相反,要从位码转换为IR汇编文本,可以使用反汇编程序:

$ llvm-dis sum.bc -o sum.ll

观察LLVM IR汇编码文件sum.ll:

; ModuleID = 'sum.c'
source_filename = "sum.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @sum(i32 %0, i32 %1) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  store i32 %1, i32* %4, align 4
  %5 = load i32, i32* %3, align 4
  %6 = load i32, i32* %4, align 4
  %7 = add nsw i32 %5, %6
  ret i32 %7
}

attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 10.0.0-4ubuntu1 "}

       整个LLVM文件的内容(无论是汇编码还是位码)被定义为一个LLVM模块。模块是LLVM IR顶层数据结构。每个模块包含一系列函数,每个函数由包含一系列指令的一系列基本块组成。模块还包含用于支持该模型的外围实体,如全局变量、目标数据布局、外部函数原型以及数据结构声明。

       LLVM局部变量与汇编语言中的寄存器类似,可以用任何以%符号开头的名称命名。因此,

%7 = add nsw i32 %5, %6

这一指令将执行两个局部变量%5和%6的加法,并将这个结果置于新的局部变量%32中。用户可以自由地给这些值命名。

       通过这个简短的例子,可以看到LLVM如何表达其基本属性:

  • 它使用静态单赋值(SSA)形式。该形式下每个变量都不会被重新赋值,每个变量只有唯一一条定义它的赋值语句。每次使用一个变量都可以立即回溯到负责其定义的唯一指令。使用SSA形式导致“使用定义链”(use-def链,既可以达到使用处的所有定义/赋值语句的集合)的生成变得非常简单。这个简化操作具有巨大的价值。UD链是经典优化(如常量传播和冗余表达式消除)的前提条件,如果LLVM没有使用SSA形式,则需要单独的数据流分析来计算UD链。
  • 代码被组织成三地址指令。数据处理指令有两个源操作数,并将结果放在不同的目标操作数中。
  • 有无穷多的寄存器。它对局部变量的最大数量没有最大限制。

target datalayout构造包含有关目标机器(target host)中描述的目标三元组(target tripple)的字节顺序和类型大小等信息。有些优化需要知道目标的特定数据布局才能完成正确的代码转化.

其中关于target datalayout的参数基本含义如下:

  • target datalayout是通过符号“-”进行分隔的规格列表;
  • E/e代表大小端;
  • m:<mangling>:名称粉碎的类型:

e:ELF mangling;

l:GOFF mangling;

m:Mips mangling;

o:Mach-O mangling;

x:Windows x86 COFF mangling;

w:Windows COFF mangling;

a:XCOFF mangling;

  • p[n]:<size>:<abi>[:<pref>][:<idx>]:n为地址空间编号,size为指针大小,abi为ABI中的指针大小,pref为地址空间n的对齐(默认等于abi),idx为地址计算的index的大小(默认等于size)。
  • S<size>:栈自然对齐的的bit数。
  • P<address space>:默认为0,表示冯诺依曼架构,数据和程序放置到同一个地址空间。
  • A<address space>:alloca分配的地址空间,默认为0。
  • G<address space>:全局变量放置的地址空间,默认为0。
  • i<size>:<abi>[:<pref>]:size为整型的对齐,abi为ABI中的对齐,pref默认等于abi。
  • v<size>:<abi>[:<pref>]:size为矢量的对齐,abi为ABI中的对齐,pref默认等于abi。
  • f<size>:<abi>[:<pref>]size为浮点的对齐,abi为ABI中的对齐,pref默认等于abi。
  • a:<abi>[:<pref>]size为聚合类型的对齐,abi为ABI中的对齐,pref默认等于abi。

上述例子中:

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

我们可以得知它具有小端字节序,采用ELF mangling进行名称粉碎,地址空间270/271的指针小为32bit,地址空间272的指针为大小为64bit,整形64bit对齐,浮点80bit对齐,自然整型为8/16/32/64bit,栈自然对齐为128bit。目标机器是装有linux-gnu的x86_64处理器。

       此外,函数声明严格遵循相应的C语法

define i32 @sum(i32 %a, i32 %b)   #0   {

此函数返回i32类型的值,并具有两个i32参数:%a和%b。本地标识符始终需要%前缀,而全局标识符使用@。LLVM支持多种类型,但最重要的类型如下:

  • iN形式的任意大小的整数,常见的例子是i32、i64和i128。
  • 浮点类型,如32位单精度浮点数float和64位双精度浮点数double。
  • 向量类型的格式位<<elements>x<elementtype>>。包含四个i32元素的向量被写为<4 x i32>.

函数声明中的#0记号映射到一组函数属性,这与C/C++函数和方法中使用的属性非常类似。

alloca指令在当前函数的堆栈帧中保留一定的空间。空间的大小由元素类型的大小决定,它遵循特定的对齐方式,例如:

  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  store i32 %1, i32* %4, align 4

该指令分配一个按4字节对齐的4字节堆栈元素。指向该堆栈元素的指针被存储在本地变量% 3中。

alloca指令通常用于表示本地变量。%0和%1参数通过store指令存储在堆栈地址%3和%4中。这些值通过load指令从相同的内存地址加载回来,并在%7 = add nsw i32 %5, %6加法中使用。最后返回加法结果%7。nsw标识指定此加法操作具有 “no signed wrap",这表示已知指令是无溢出的,从而允许进行一些优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LLVM IR格式的基本介绍 的相关文章

随机推荐

  • 【算法题】运矿石(未完待续)

    题目 小v最近在玩一款挖矿的游戏 该游戏介绍如下 1 每次可以挖到多个矿石 每个矿石的重量都不一样 挖矿结束后需要通过一款平衡矿车运送下山 2 平衡矿车有左右2个车厢 中间只有1个车轮沿着导轨滑到山下 且矿车只有在2个车厢重量完全相等且矿石
  • cass等距离等分线段的命令键_cad直线均分的命令(CAD等分线段快捷键?)

    CAD等分线段快捷键 CAD中等分线段分为两种 定数等分和定距等分 1 定数等分 命令是DIVIDE 快捷键是DIV 2 定距等分 命令是MEASURE 快捷键是ME 以线段定数等分为例 1 键盘输入快捷键 DIV 如图 2 按回车键或者空
  • 常用的免费Api接口网址

    收录一下常用的免费Api接口 记录参考 具体使用请自行前往查看 和风天气 https dev qweather com docs api 天气预报 https www juhe cn docs api id 73 手机号码归属地 https
  • Android Studio代码提示自动补全设置

    最近学习Android开发课程 用的是Android studio开发工具 刚开始用发现竟然没有代码提示补全功能 我自己去看了一下设置 又设置了匹配补全提示 code起来还是不行 后来上网搜索 都是一些关于如何设置个性化自动补全提示的内容
  • BC1.2快充协议介绍

    BC1 2定义 BC1 2 Battery Charging v1 2 是USB IF下属的BC Battery Charging 小组制定的协议 主要用于规范电池充电的需求 该协议最早基于USB2 0协议来实现 BC1 2充电端口 USB
  • 有无监督,上下游任务,高斯分布,BN总结

    1 无监督和有监督的区别 有无标号 label与预测结果做损失loss transformer有监督的 BERT 在预训练中在没有标号的数据集上训练 在微调的时候同样是用一个BERT模型 但是它的权重被初始化成在预训练中得到的权重 有标号的
  • 华为OD机试 - 字符串加密(Java)

    题目描述 给你一串未加密的字符串str 通过对字符串的每一个字母进行改变来实现加密 加密方式是在每一个字母str i 偏移特定数组元素a i 的量 数组a前三位已经赋值 a 0 1 a 1 2 a 2 4 当i gt 3时 数组元素a i
  • 软件工程学习过程中工具、资料汇总与心得

    因为在上了半年课以后 发现学的课程太杂 要的工具太多 回顾当初找工具找到病毒工具的苦不堪言的黑历史 在此整理学习用到的所有工具 保持更新 因为文件已经被别人上传了 还要积分什么鬼的 信息化时代共享不好嘛 因此将文件均上传至百度网盘 下载缓慢
  • vue+nodejs 搭建网站全过程

    Vue js Node js MongoDB 的网站搭建示例 安装和初始化项目 使用 Vue Cli 初始化前端项目 vue create my site 使用 Express 初始化后端项目 npx express generator m
  • 如何解决局域网广播风暴

    晚唐诗人许浑曾写过一首诗 咸阳城东楼 其中有一句名句 被传诵千古 山雨欲来风满楼 山雨欲来风满楼 是全诗的警句 周围的群山 雨意越来越浓 大雨即将到来 城楼上 已是满楼的狂风 全句只有寥寥七个字 却十分形象地写出了山城暴雨即将来临时的情景
  • 华为OD机试 - 阿里巴巴找黄金宝箱(I)(Python)

    题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上 无意中发现了强盗集团的藏宝地 藏宝地有编号从0 N的箱子 每个箱子上面贴有一个数字 箱子中可能有一个黄金宝箱 黄金宝箱满足排在它之前的所有箱子数字和等于排在它之后的所有箱子数字之和 第一个箱子
  • SQL SERVER行列不同分类的展示---PIVOT

    行列不同分类的SQL SERVER展示 由于工作的需求 需要对行不同分类 列也不同分类 可以将行分类之后对列进行每列CASE WHEN 进行展示 但是这种方法太蠢了 而且代码不够简洁 因此网上寻找了行转列函数 上最基础的做法 select
  • 关于javascript中number类型与string类型的比较

    javascript中number类型与string类型的比较 应该是根据number类型的数值情况 将string转换为与number数值相对应的值再比较 var numVal 10 00 if numVal 10 0000 consol
  • 搭建QNX开发环境-qnx系统环境开发

    锋影 e mail 174176320 qq com QNX是可以提供试用30天 目前发布最新的是qnx7 0版本 申请也是只能7 0 做好白老鼠的准备 老版本不再申请试用 其实多数时候 老版本的650 650sp1 和较新稳定的660版本
  • caffe 查看caffemodel中的参数与数据

    在用caffe训练完一个模型之后 我们想更加直观的查看这个模型该怎么做呢 caffe框架训练出来的caffemodel是一个类似于黑盒的东西 我们无法直接看到它的本质 需要借助caffe所定义的接口来协助我们 详细的文档在caffe官网上都
  • gcc链接脚本和启动文件详解

    C代码生成可执行程序分为 预编译 编译 汇编 链接四个阶段 预处理器把源程序聚合在一起 并把宏定义转换为源语言 编译器根据预处理的源程序生成汇编程序 汇编器处理汇编程序 生成可重定位的机器代码 连接器将可重定位的目标代码和库文件连接到一起
  • 基于51单片机直流电机PID调速PWM输出LCD1602液晶显示设计

    视频演示地址 https www bilibili com video BV1LK4y1R7ju 该设计是由AT89C51单片机为主控芯片显示为1602液晶构成直流电机调速 开机默认不转按下启动后电机开始运行 PID控制PWM进行调速 按键
  • Arduino使用ESP8266模块联网

    ESP8266模块准备 1 透传程序烧写 2 Arduino与ESP8266接线 Arduino模块程序 测试 总结 上一篇文章已经介绍了 利用 ArduinoIDE开发ESP8266模块 这篇文章介绍一下arduino怎么通过ESP826
  • unity鼠标事件

    鼠标事件 鼠标事件 都是当鼠标和gui或者碰撞体 Collider 交互时候触发 需要说明的是drag其实就是鼠标down后up之前持续每帧都会发送此消息 OnMouseDown 当鼠标上的按钮被按下时触发的事件 OnMouseDrag 当
  • LLVM IR格式的基本介绍

    LLVM IR以两种格式存储在磁盘上 1 位码 bc文件 2 汇编文本 ll文件 以sum c源代码为例 int sum int a int b return a b 使用Clang生成位码 命令如下 clang sum c emit ll