LLVM IR(一)——如何使用LLVM编译执行代码

2023-11-20

可以转载,请注明出处!

在阅读这一章节之前,需要本地安装llvm环境,没安装可以参考这里:https://blog.csdn.net/qq_42570601/article/details/107146407

1.1 LLVM IR的三种结构

LLLLVM的代码有3种表示形式(三种形式等价):

  • 1)内存编译器中的IR,用户不可知。
  • 2)存于磁盘的 bitcode,是一个二进制文件,以.bc为后缀,用户可以看到,但是看不懂。
  • 3)用户可读的汇编码,这个就是我们要学习和编写的IR,以.ll为后缀。

1.2将C文件转为LLVM IR汇编码

1> 首先在你已经安装了llvm环境的Linux系统中,选择一个你方便的目录,创建一个*.c文件,文件中用C的语法写一个简单的程序,比如输出hello world,下面我创建的是tpy.c文件。

在这里插入图片描述
在这里插入图片描述

//tpy.c文件
#include <stdio.h>

int main(){
        printf("Hello World!");
		return 0}

2> 使用以下命令来将C语言代码转换成LLVM IR:clang -emit-llvm -S tpy.c -o tpy.ll
这里有所有的命令:https://llvm.org/docs/CommandGuide/index.html

在这里插入图片描述

3> 生成如下的LLVM IR文件tpy.ll:

; ModuleID = 'tpy.c'
source_filename = "tpy.c"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@.str = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1

; Function Attrs: noinline nounwind optnone uwtable
define i32 @main() #0 {
entry:
  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="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"="+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 6.0.0 (tags/RELEASE_600/final)"}

此时的tpy.ll文件还不能执行,因为这是一种用户可读的IR中间码,如果要执行该文件,还需要将其转成二进制文件bitcode。

1.3将LLVM IR汇编码转为bitcode

执行以下命令把tpy.ll文件的LLVM IR转为bitcode格式:llvm-as tpy.ll –o tpy.bc
在这里插入图片描述
生成的tpy.bc文件内容如下:
在这里插入图片描述

1.4执行LLVM bitcode

执行命令:lli tpy.bc,可以输出如下内容:

在这里插入图片描述

1.5链接LLVM bitcode

  • 1.、为了展示llvm-link的功能,首先在不同文件中编写两段代码,其 中一个引用另一个:
// $ cat test1.c 被引用文件
 int func(int a) {
 a = a*2;
 return a; 
 }
// $ cat test2.c 引用文件
 #include<stdio.h>
 extern int func(int a);
int main() {
 int num = 5;
 num = func(num);
 printf("number is %d\n", num);
 return num;
 } 
  • 2、使用以下命令将C代码转换成位流文件格式,先转成.ll文件,再 将.ll文件转成.bc文件:
clang -emit-llvm -S test1.c -o test1.ll 
clang -emit-llvm -S test2.c -o test2.ll 
llvm-as test1.ll -o test1.bc 
llvm-as test2.ll -o test2.bc 

我们得到了test1.bc和test2.bc,而test2.bc引用了test1.bc文件中的func 语法。

  • 3、通过如下方式使用llvm-link命令链接两个LLVM bitcode文件:
llvm-link test1.bc test2.bc –o output.bc
  • 4、执行output.bc文件
lli output.bc

1.6自己写一个IR然后编译执行

IR基本语法参考链接:https://blog.csdn.net/qq_42570601/article/details/107157224

在你已经安装了llvm环境的Linux系统中,选择一个你方便的目录,创建一个.ll文件,编写一段IR代码,然后同1步骤中的一样:
llvm-as tpy.ll –o tpy.bc,用该命令汇编。
lli tpy.bc,用该命令执行。

在这里插入图片描述

上面这个程序的输出结果是31。

1.7编译C接口的API,执行生成IR

使用API参考链接:https://blog.csdn.net/qq_42570601/article/details/107771289

编写生成IR的C++代码

生成IR有以下几种方式:

需要会使用的是2、3,IRBuilder是对C接口指令类的封装,所以这两个要结合看,用2生成module、function等,用到指令就用IRBuilder。

在你已经安装了llvm环境的Linux系统中,选择一个你方便的目录,创建一个.cpp文件,编写C++代码。

编译C++代码生成可执行文件

下面main.cpp就是一个用C++编写的自动生成IR的代码,编写好代码后,使用下面命令即可生成可执行文件:

clang++ -O3 main.cpp -o main `llvm-config --cflags --ldflags` `llvm-config --libs` `llvm-config --system-libs`

在这里插入图片描述

使用./main命令执行可执行文件main,执行结果如下:

在这里插入图片描述

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

LLVM IR(一)——如何使用LLVM编译执行代码 的相关文章

  • 在 Ubuntu 16.04 上找不到 printf.c

    我最近切换到Ubuntu 16 04 我在用vscode作为 Ubuntu 上的 IDE 我配置了其他语言 但我无法做到这一点C C 我创建c cpp properties json launch json tasks json 当我开始编
  • Linux shell 脚本:十六进制数字到二进制字符串

    我正在 shell 脚本中寻找一些简单的方法来将十六进制数字转换为 0 和 1 字符的序列 Example 5F gt 01011111 是否有任何命令或简单的方法来完成它 或者我应该为其编写一些开关 echo ibase 16 obase
  • Bash 方法的返回值总是模 256

    我有一个 bash 脚本方法 它返回输入值 然而 返回值始终是模 256 的值 我用 google 搜索了一段时间 发现this http www tldp org LDP abs html exitcodes html文章说它总是以 25
  • 适用于 KDE 和 Gnome 的 Gui [重复]

    这个问题在这里已经有答案了 我想为一个现在是 CLI 的应用程序编写一个 gui 它需要在 KDE 和 Gnome DE 中 看起来不错 充分利用用户的外观设置 如果我选择 Qt 或 GTK 我能够做到这一点吗 它们与两个 DE 集成良好吗
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • Linux shell 脚本中的 while 循环超时

    这工作正常 无限循环 while TRUE do printf done 我在尝试着timeout this while loop与timeout命令 所有这些都不起作用 timeout 5 while TRUE do printf don
  • 没有可用的符号表信息

    我正在测试第三方的库 它崩溃了 当我想查看崩溃的原因时 我的 gdb 告诉我没有可用的调试符号 Program received signal SIGSEGV Segmentation fault Switching to Thread 0
  • 在 /dev/input/eventX 中写入事件需要哪些命令?

    我正在开发一个android需要将触摸事件发送到 dev input eventX 的应用程序 我知道C执行此类操作的代码结构如下 struct input event struct timeval time unsigned short
  • PHP 致命错误:未找到“MongoClient”类

    我有一个使用 Apache 的网站 代码如下 当我尝试访问它时 我在 error log 中收到错误 PHP Fatal Error Class MongoClient not found 以下是可能错误的设置 但我认为没有错误 php i
  • Godaddy 托管上的 CakePHP 控制台

    我一直在努力让我的 CakePHP 网站在 Godaddy 网格托管 帐户上运行 我的蛋糕应用程序设置是从帐户的子目录托管的 并且可以通过子域访问 我必须调整我的 htaccess 文件才能使其正常工作 现在我需要让 CakePHP 控制台
  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 修改linux下的路径

    虽然我认为我已经接近 Linux 专业人士 但显然我仍然是一个初学者 当我登录服务器时 我需要使用最新版本的R 统计软件 R 安装在 2 个地方 当我运行以下命令时 which R I get usr bin R 进而 R version
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • 从 csv 文件中删除特定列,保持输出上的相同结构[重复]

    这个问题在这里已经有答案了 我想删除第 3 列并在输出文件中保留相同的结构 输入文件 12 10 10 10 10 1 12 23 1 45 6 7 11 2 33 45 1 2 1 2 34 5 6 I tried awk F 3 fil
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C

随机推荐

  • 开启电脑ssl协议的方法

    转自 微点阅读 https www weidianyuedu com 电脑ssl协议怎么开启 开启ssl协议的方法是什么 经近期实际操作了解到开启ssl协议一共需要6个步骤 很快即可完成 以下是开启电脑ssl协议的方法介绍 1 首先打开浏览
  • html src 参数,HTTP参数解析

    本文概述 在本节中 我们将讨论各种HTTP参数及其语法 例如 日期和时间格式 字符集等 这些参数用于在编写客户端或服务器的HTTP程序时构造请求和响应消息 HTTP的各种参数如下 HTTP版本 为了指示协议的版本 HTTP使用 编号方案 协
  • 办公网络上网行为管理规划

    办公网络上网行为管理规划是确保办公网络资源的合理利用和保障网络安全的重要措施 下面是办公网络上网行为管理规划的一般性步骤和原则 确立政策和准则 制定明确的上网行为管理政策和准则 明确员工在办公网络上的合规要求和行为规范 包括规定员工上网内容
  • 项目设计:基于YOLO目标检测算法的安全帽/口罩/汽车/行人/交通标志...检测

    本文将详细介绍YOLO目标检测算法 该算法支持各种目标检测 包括 安全帽 汽车 造价 交通标志 等 其他毕业设计题目推荐参考 毕业设计 电子 通信 计算机 物联网专业毕业设计选题参考 嵌入式linux 单片机STM32 web 图像 htt
  • 数据库难点知识

    索引 当表中有大量记录时 若要对表进行查询 第一种搜索信息方式是全表搜索 是将所有记录一一取出 和查询条件进行一一对比 然后返回满足条件的记录 这样做会消耗大量数据库系统时间 并造成大量磁盘I O操作 第二种就是在表中建立索引 然后在索引中
  • matlab通用操作界面窗口包括哪些,matlab作业题

    第一章 MATLAB环境 1 MATLAB通用操作界面窗口包括哪些 命令窗口 历史命令窗口 当前目录窗口 工作空间窗口各有哪些功能 答 MATLAB通用操作界面窗口包括 命令窗口 历史命令窗口 当前目录浏览器窗口 工作空间窗口 变量编辑器窗
  • 前端的工程化、模块化和组件化

    什么是工程化 工程化是一种思想而不是某种特定的技术 当然我们在实现项目工程化的过程中 我们也会去使用一些技术 前端工程化是使用软件工程的技术和方法来对前端的开发流程 技术 工具等进行规范化 标准化 其主要目的为了提高效率和降低成本 即提高开
  • 使用Class.forName 自动完成注册驱动,简化代码 但是 “//” 是使用最多的

    方式1 public void connect05 throws IOException ClassNotFoundException SQLException 通过properties对象获取文件信息 Properties propert
  • Python爬虫突破封禁的6种常见方法

    在互联网上进行自动数据采集 抓取 这件事和互联网存在的时间差不多一样长 今天大众好像更倾向于用 网络数据采集 有时会把网络数据采集程序称为网络机器人 bots 最常用的方法是写一个自动化程序向网络服务器请求数据 通常是用 HTML 表单或其
  • select2 获取选中的值

    获取选中的名 var cardTypeW cardType option checked text 获取选中的值 写法1 var cardTypeW cardType option checked val 写法2 var cardTypeW
  • js逆向-某旗小说

    声明 本文仅供学习参考 请勿用于他途 违者后果自负 前言 笔者一直是一个小说控 喜欢看小说很多年了 自从学会了python后 就经常会去不同的小说网站抓取小说保存到本地阅读 最近发现一本很好看的小说 准备抓下来看 却发现有请求参数和返回的接
  • webpack的构建流程

    一 运行流程 webpack 的运行流程是一个串行的过程 它的工作流程就是将各个插件串联起来 在运行过程中会广播事件 插件只需要监听它所关心的事件 就能加入到这条webpack机制中 去改变webpack的运作 使得整个系统扩展性良好 从启
  • opencv生成棋盘格

    头文件 include
  • 前端将List列表转化为树型结构(reduce函数)

    主要用到了reduce 函数 for循环可以做到的事情reduce 都可以做到 甚至操作起来更加简单方便和高雅 reduce 为数组中的每一个元素依次执行回调函数 不包括数组中被删除或从未被赋值的元素 reduce语法 array redu
  • 使用我们的actionbar实现我们的tab导航功能(详解)

    第一步的话就是创建我们对应的fragment 这里的话我们创建了三个对应的fragment 第二步的话就是创建我们的mytablistener类 package com example handle Fragments import and
  • 超简单:很火的3D立体动态相册,送给心爱的那个人

    1 首先 我们一共需要三个文件 目录关系如下所示 先建index html文件吧 电脑上先创建一个 txt文件 在里面加入代码后保存 重命名为index html 记得把原来的 txt后缀覆盖 html我用的谷歌浏览器 index html
  • pg_receivewal实践

    测试从pg receivewal的日志中恢复从库为主库 主从配置async模式 配置pg receivewal接收日志pg receivewal D dbaas pg data pg receivewal data v h 10 9 10
  • 动态模型系列笔记(一)——隐马尔可夫模型(HMM)

    隐马尔可夫模型 背景介绍 提纲 隐马尔可夫模型 HMM 符号表示 两个假设 三个问题 Evaluation Learning Decoding 小结 附录 背景介绍 隐马尔可夫模型 HMM 是一种概率图模型 我们知道 机器学习模型可以从频率
  • 自创简易加密算法

    前几日和同事聊天 说到经常忘记密码 但记在一些地方 又不放心 我们就想 要是实现一个加密算法 每次记录加密结果 需要时再解密 那问题不就迎刃而解了嘛 后来根据需求 设计了一个基于异或的对称加密算法 算法非常简单 1 先定义一个由一系列不规则
  • LLVM IR(一)——如何使用LLVM编译执行代码

    可以转载 请注明出处 文章目录 1 1 LLVM IR的三种结构 1 2将C文件转为LLVM IR汇编码 1 3将LLVM IR汇编码转为bitcode 1 4执行LLVM bitcode 1 5链接LLVM bitcode 1 6自己写一