Ubuntu18.04 编译安装llvm-clang

2023-11-17

背景知识

LLVM和GCC的区别
传统编译器
传统编译器的工作原理基本上都是三段式的,可以分为前端(Frontend)、优化器(Optimizer)、后端(Backend)。前端负责解析源代码,检查语法错误,并将其翻译为抽象的语法树(Abstract Syntax Tree)。优化器对这一中间代码进行优化,试图使代码更高效。后端则负责将优化器优化后的中间代码转换为目标机器的代码,这一过程后端会最大化的利用目标机器的特殊指令,以提高代码的性能。
事实上,不光静态语言如此,动态语言也符合上面这个模型,例如Java。Java Virtual Machine也利用上面这个模型,将Java代码翻译为Java bytecode。
这一模型的好处是,当我们要支持多种语言时,只需要添加多个前端就可以了。当需要支持多种目标机器时,只需要添加多个后端就可以了。对于中间的优化器,我们可以使用通用的中间代码。
这种三段式的结构还有一个好处,开发前端的人只需要知道如何将源代码转换为优化器能够理解的中间代码就可以了,他不需要知道优化器的工作原理,也不需要了解目标机器的知识。这大大降低了编译器的开发难度,使更多的开发人员可以参与进来。
虽然这种三段式的编译器有很多有点,并且被写到了教科书上,但是在实际中这一结构却从来没有被完美实现过。做的比较好的应该属Java和.NET虚拟机。虚拟机可以将目标语言翻译为bytecode,所以理论上讲我们可以将任何语言翻译为bytecode,然后输入虚拟机中运行。但是这一动态语言的模型并不太适合C语言,所以硬将C语言翻译为bytecode并实现垃圾回收机制的效率是非常低的。
GCC也将三段式做的比较好,并且实现了很多前端,支持了很多语言。但是上述这些编译器的致命缺陷是,他们是一个完整的可执行文件,没有给其它语言的开发者提供代码重用的接口。即使GCC是开源的,但是源代码重用的难度也比较大。
LLVM
LLVM最初是Low Level Virtual Machine的缩写,定位是一个虚拟机,但是是比较底层的虚拟机。它的出现正是为了解决编译器代码重用的问题,LLVM一上来就站在比较高的角度,制定了LLVM IR这一中间代码表示语言。LLVM IR充分考虑了各种应用场景,例如在IDE中调用LLVM进行实时的代码语法检查,对静态语言、动态语言的编译、优化等。
LLVM与GCC在三段式架构上并没有本质区别。LLVM与其它编译器最大的差别是,它不仅仅是Compiler Collection,也是Libraries Collection。举个例子,假如说我要写一个XYZ语言的优化器,我自己实现了PassXYZ算法,用以处理XYZ语言与其它语言差别最大的地方。而LLVM优化器提供的PassA和PassB算法则提供了XYZ语言与其它语言共性的优化算法。那么我可以选择XYZ优化器在链接的时候把LLVM提供的算法链接进来。LLVM不仅仅是编译器,也是一个SDK。

编译安装llvm

1.安装build-essential(要的是里面的make和gcc),cmake,svn

sudo apt-get install build-essential
sudo apt install cmake
sudo apt-get install subversion

2.下载llvm源代码
进入官网https://releases.llvm.org/download.html,这里我下载的5.0.0
在这里插入图片描述
3.解压(注意这里要解压两次)

xz -d 文件
tar -xvf 文件

把cfe改为clang,llvm改为llvm,将clang放入llvm/tools文件夹下,并创建一个LLVM,将llvm放入,并创建build,test文件夹
在这里插入图片描述
注:可能涉及到的开锁命令:sudo chown 用户名 文件夹/ -R
4.build目录下:cmake ../llvm -DLLVM_TARGETS_TO_BUILD=X86 -DCMAKE_BUILD_TYPE=Release
make -j4(这里我多次出现了Makefile151的问题,有两种可能,一个是虚拟机内存不够,另外一个是llvm版本与Ubuntu当前版本不兼容)

make install

如图,安装成功

手写pass(这里原理还不是很明白)

1.准备输入文件,点开test,新建input.c

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

int sub()
{
	int a = 1;
	int b = 2;
	int c = b-a;

	return c;
}

同目录下:clang -O0 -S -emit-llvm input.c -o input.ll
其中-O0是指optimazation 0,也就是优化等级为0的意思。
也可以用下面这条输出机器码类型:clang -O0 -c -emit-llvm input.c -o input.ll
input.ll:
在这里插入图片描述
2.(1)在llvm/lib/Transforms文件夹下创建一个文件,这里取名如下,自定义的pass就放在这里
在这里插入图片描述
从Hello文件夹下复制三个文件到OpcodeCounter下,并修改对应的文件名
在这里插入图片描述
(2)修改OpcodeCounter.cpp内容:

#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

namespace//这个所谓的匿名namespace,实际就是一个子类,下面写了继承自FunctionPass,说明咱们搞的这个类输入是一个Function
{
	// OpcodeCounter - The first implementation, without getAnalysisUsage.
	struct OpcodeCounter : public FunctionPass 
	{
		static char ID; // Pass identification, replacement for typeid
		OpcodeCounter() : FunctionPass(ID) {}//构造函数

		bool runOnFunction(Function &F) override
		{
			std::map<std::string,int> opcode_map;//一个类似python中dict的类型,不了解python就理解成结构体

			errs() << "Function name: ";
			errs().write_escaped(F.getName()) << '\n';//显示遍历的函数名字
			for(Function::iterator bb = F.begin(),e = F.end();bb!=e;bb++)//在funciton中遍历basicblock
			{
				errs() << "BasicBlock name: "<< bb->getName() <<"\n";
				errs() << "BasicBlock size: "<< bb->size() <<"\n";//显示basicblock的名字和大小
				for(BasicBlock::iterator i = bb->begin(),i2 = bb->end();i!=i2;i++)//在bb中遍历statement
				{
					errs() << "              "<< *i<<"\n";
					if(opcode_map.find(i->getOpcodeName())==opcode_map.end())//找statement中的运算符,为了数ll文件中各个运算符出现的次数
					{
						opcode_map[i->getOpcodeName()] = 1;//第一次见到某个运算符置1,以后再见到就+1
					}
					else
					{
						opcode_map[i->getOpcodeName()]+=1;
					}
					//examples of user and use
					Instruction *inst = dyn_cast<Instruction>(i); 
					if(inst->getOpcode() == Instruction :: Add)//如果见到运算符是add,下面先显示用到它的语句,再显示它所调用的语句,注意一个用指针,一个用地址
					{
						for(User *U :inst ->users())
						{
							if(Instruction *Inst = dyn_cast<Instruction>(U))
							{
								errs()<<"result of add used in : "<<*Inst <<"\n";
							}
						}
						for(Use &U :inst ->operands())
						{
							Value *v =U.get();
							errs()<<"input of add originate from : " <<*v<<"\n";
						}
					}
				}

			}
			errs()<<"------------------------------\n";//这里把前面数出来的各个运算符的个数显示出来
			errs()<<"summary:\n";
			std::map<std::string,int>::iterator i = opcode_map.begin();
			std::map<std::string,int>::iterator e = opcode_map.end();
			while(i!=e)
			{
				errs()<<"number of "<< i->first << ":"<< i->second <<"\n";
				i++;
			}
			errs()<<"\n";
			opcode_map.clear();
			return false;
		}
	};
}

char OpcodeCounter::ID = 0;
static RegisterPass<OpcodeCounter> X("OpcodeCounter", "OpcodeCounter Pass");//在RegisterPass中注册我们自定义的这个pass

(3)改Transform文件夹下的CMakeList.txt
在最后加一行add_subdirectory(OpcodeCounter)告诉llvm我们加了这么一个文件
第二个是我们自己新建的OpecodCounter文件夹里面的CMakeList.txt
在这里插入图片描述
第一处为同文件夹下exports的名字,第二处为将来通过llvm的opt命令最终生成的.so文件起的名字,第三处为同文件夹下cpp的名字。
(4)生成so文件
在build目录下执行make命令
在这里插入图片描述
5)用so文件优化ll文件
在test目录下:

opt -load /home/czh/Desktop/LLVM/build/lib/LLVMOpcodeCounter.so -OpcodeCounter input.ll

输出结果为:
在这里插入图片描述
在这里插入图片描述

https://www.cnblogs.com/zuopeng/p/4141467.html
https://zhuanlan.zhihu.com/p/118664682

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

Ubuntu18.04 编译安装llvm-clang 的相关文章

  • 如何查看 Ubuntu 上的 Binutils 版本?

    我已经搜索过 但没有找到一个选项来告诉我我的 Ubuntu 上有哪个版本的 binutils 或者至少我不知道如何解释它 gcc v 没有透露任何有关 binutils 的信息 ld v 告诉我GNU ld GNU Binutils for
  • 如何使用 Beyond Compare 3 作为 svn 的 diff3-cmd?

    I saw this https stackoverflow com questions 294286 how to use svn with beyond compare 3帖子解释了如何让 BC3 作为 Subversion 的 dif
  • opencv_contrib编译错误:类没有成员

    我必须实现 SURF 算法来进行图像拼接 我在使用列出的库时遇到了问题here https stackoverflow com questions 33560251 opencv 3 0 0 ubuntu 14 04 nonfree non
  • 在 subversion 中看到许多提交的组合差异?

    我被要求审查 SVN 版本号 123 178 199 245 和 288 中所做的更改 这些都是与特定功能相关的提交 解决这个问题的合理方法是什么 我想我真的想以某种方式查看收集的差异 但我愿意接受建议 我们现在正在修订 400 编辑 我想
  • 使用 Maven 外部化 SCM 凭证

    有没有一种方法可以外部化我的 SCM 凭据 以便它们不会存储在项目的 POM 中 问题是 如果它们包含在项目的 POM 中 那么在部署项目时它们将对所有人可见 对于某些 SCM 提供商 您可以在
  • Ubuntu systemd 自定义服务因 python 脚本而失败

    希望获得有关 Ubuntu 中的 systemd 守护进程服务的一些帮助 我写了一个 python 脚本来禁用 Dell XPS 上的触摸屏 这更像是一个问题 而不是一个有用的功能 该脚本可以工作 但我不想一直启动它 这就是为什么我想到编写
  • uWSGI 皇帝权限被拒绝,除非 root

    我尝试使用二进制文件本身的标志 uid www data gid www data 并将其设置在我的配置中 uid www data gid www data 但套接字总是由我正在使用的帐户生成 因此我从 nginx 收到权限被拒绝的错误
  • C++ 标准是否允许未初始化的 bool 导致程序崩溃?

    我知道一个 未定义的行为 C 几乎可以让编译器做任何它想做的事情 然而 我遇到了一次令我惊讶的崩溃 因为我认为代码足够安全 在这种情况下 真正的问题仅发生在使用特定编译器的特定平台上 并且仅在启用优化的情况下发生 我尝试了几种方法来重现问题
  • SVN:如何解决“文件已被替换”状态

    我正在修改文件 重命名它们并切换它们 我正在测试替代主页 现在我收到一条状态消息 上面写着 文件已被替换 和一个 R 我不知道该怎么做才能解决这个问题 我正在使用Coda 但它没有解决这个问题 所以我想这是命令行时间 我关心的版本是我的本地
  • ubuntu 的 CSS 更少(并且自动编译)? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我尝试过 simples 但现在 l
  • 如何从 Chrome 扩展示例(subversion 存储库)下载所有文件?

    我要下载这个例子 http src chromium org viewvc chrome trunk src chrome common extensions docs examples api tabs 它们是使用 ViewVC 显示的
  • Rstudio 更有意义的窗口标题

    我在 Ubuntu 16 04 下使用 R studio 版本 1 0 143 窗口标题仅显示一个非常无信息的 RStudio 我希望至少有当前选项卡的名称 或者最好是与此选项卡对应的文件的完整路径 在 Windows 下 完整路径似乎出现
  • dpkg 错误:pycompile:未找到

    sudo apt get remove purge mysql server mysql client mysql common 当我尝试使用上述命令删除 mysql 时 出现以下错误 Reading package lists Done
  • Ubuntu 16.04/Django - Gunicorn - Worker 无法启动

    我正在 Digital Ocean Ubuntu 16 04 VPS 上部署 Django 项目 我使用的是Django的一键安装 然后替换为我的项目 问题是服务器返回502 Error EDIT 没有realestate scanner
  • 请检查 PPA 名称或格式是否正确

    在我的 Ubuntu 14 04 中 我尝试安装 Captiva 图标包 如上所列这个 omgubuntu 帖子 http www omgubuntu co uk 2014 09 4 gorgeous linux icon themes d
  • 找不到 cygwin setup.exe 文件?

    我正在尝试将 subversion 数据包添加到 cygwin 为此我需要运行 setup exe 但我在 cygwin 文件夹中找不到它 它会位于哪里 它不是incygwin 文件夹 它位于您上次安装时放置的位置 很可能是垃圾箱或临时目录
  • PostgreSQL 错误:无法连接到数据库 template1:​​无法连接到服务器:没有这样的文件或目录

    我需要创建数据库 首先我运行 sudo su postgres then createdb test 我不断收到此错误 createdb could not connect to database template1 could not c
  • 使用 --prof 选项创建多个日志文件而不是一个 v8.log 的节点

    我正在尝试使用 prof 选项来分析我的 Node 应用程序 但我发现不是一个单一的 v8 log 文件 而是使用诸如isolate 0x9582b40 v8 log isolate 0xa1cab78 v8 6049 等前缀创建的多个文件
  • 我可以在 Ubuntu 上使用 Homebrew 吗?

    我只是尝试使用 Homebrew 和 Linuxbrew 在我的 Ubuntu 服务器上安装软件包 但都失败了 这就是我尝试安装它们的方法 sudo apt get install build essential curl git m4 r
  • Subversion 中的版本和项目的良好存储库布局是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们有标准的 Subversion 主干 分支 标签布局 我们有几个针对中长期项目的分支 但到目前为止还没有一个发布版本 这正在快速逼近 我们应

随机推荐

  • 2019.9.27 csp-s模拟测试53 反思总结

    这个起名方式居然还有后续 为什么起名不是连续的 T1想了半天 搞出来了 结果数组开小 其实是没注意范围 T2概率期望直接跳 后来翻回来写发现自己整个理解错了期望的含义 何 T3错误想到赛道修建结果来了个错误贪心 关于T2破罐子破摔输出k居然
  • SPSS知识点复习

    一 T检验 对连续变量使用的方法 T检验 方差检验 1 均值 Means 过程 完成数据分组输出描述统计量 2 T检验 用t分布理论来推论差异发生的概率 从而比较两个平均数的差异是否显著 前提 总体服从正态分布 样本量不超过30 3 单样本
  • [Bug集合]terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

    terminate called after throwing an instance of std bad alloc what std bad alloc 超内存了兄dei 我出现这个问题是因为读入了大量图片 结果系统提示这个信息
  • 解决flex布局中 space-between方法的排版问题

    flex布局中 justify content space between方法的排版问题 flex给我们的布局带来了很大的方便 但有时候也会碰到一些问题 比如space between最后一行元素的排列问题 问题 假如我们有8个元素 ul
  • Lethean结点搭建

    文章目录 结点搭建 日志位置 钱包地址 Lethean官网 https github com LetheanMovement lethean github地址 https github com LetheanMovement lethean
  • 华为OD机试真题-热点网站统计-2023年OD统一考试(B卷)

    题目描述 企业路由器的统计页面 有一个功能需要动态统计公司访问最多的网页URL top N 请设计一个算法 可以高效动态统计Top N的页面 输入描述 每一行都是一个URL或一个数字 如果是URL 代表一段时间内的网页访问 如果是一个数字N
  • String.format()方法使用详解技巧

    一 时间切割 String year String format tY 2020 04 30 2020 String month String format tm 2020 04 30 04 String day String format
  • [454]bokeh之bokeh.layouts

    如果希望在同一张图上显示多个图像 可以使用bokeh layouts类中的方法 row column gridplot widgetbox layout row row 的作用是将多个图像以行的方式放到同一张图中 from bokeh io
  • 出现Command ‘locate‘ not found,but can be installed with:apt install mlocate解决方法

    出现Command locate not found but can be installed with apt install mlocate解决方法 在使用Ubuntn出现Command locate not found but can
  • 以太坊区块链浏览器搭建

    链客 专为开发者而生 有问必答 此文章来自区块链技术社区 未经允许拒绝转载 当然 读者若要实践 那么电脑上必须已经搭建好了geth 并且命令 geth version 能显示版本信息 针对以太坊各个链 私链 公链 测试链 都可以用该篇文章来
  • Keil MDK误将Project窗口关了的解决办法,窗口视图重置

    在使用MDK时 误将Project窗口或者其他窗口关了 点击view 选择对应的窗口即可 或者点击Window窗口 选择Reset View to Defaults 再点击Reset即可实现窗口的重置
  • 项目管理:要做一项任务,不要做一堆事儿

    作为项目经理 我们最终的任务和目标是把项目高标准的完成 在完成最终目标的过程中离不开项目成员的协作配合和任务工作的分配 只有项目组成员各司其职 高效的完成各自的工作 才能保证项目的效率和质量 那么如何保证项目组成员在完成各自任务的时候既能保
  • 打包vue前端docker镜像

    1 安装好docker环境 docker v 查看是否成功 2编写Dockerfile文件 下面这个dokcerfile的RUN指令不好 当有多个命令需要执行的时候 可以用换行符和连接符隔开 而不是写多个RUN指令 因为那样会增加镜像的构建
  • Go基础(包、变量和函数):开启Go语言之旅

    开启Go语言之旅 Go编程语言是一个开源项目 可以让程序员提高工作效率 Go是富有表现力 简洁 干净和高效的 其并发机制使编写充分利用多核和联网机器的程序变得容易 而其新颖类型系统则可实现灵活的模块化程序构建 快速编译为机器代码 但具有垃圾
  • apple资讯

    6 月 10 日消息 macOS 12 Monterey 支持通过 AirPlay 将内容发送到第二台 Mac 上 用户还可以使用该功能进行屏幕镜像 将一台备用机器变成一个外部显示器 除了使用 AirPlay 无线方式外 macOS 12
  • MATLAB雷达空时自适应处理

    空时自适应处理是一个用来描述同时处理空域和时域的自适应阵列的术语 信号的空域分量由阵列传感器收集 与所有阵列工作相同 而信号的时域分量用每个阵列传感器后等间隔延时单元产生 为此目的 一个尺寸N阵列有N个子通道 每个传感器后面对应一个 在每个
  • Java Servlet生成Json格式数据

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Java Servlet生成Json格式数据 分类 Web JAVA2013 09 17 14 38 4805人阅读 评论 1 收藏 举报 在Servlet中覆写doGet
  • java 提交表单_http常见的form表单请求方式

    在Web开发中 我们使用的比较多的HTTP请求方式基本上就是GET POST 一 http请求常见的表单文件上传形式 首先了解下application x www form urlencoded和multipart form data的区别
  • 渗透测试-木马免杀的几种方式

    前言 免杀 又叫免杀毒技术 是反病毒 反间谍的对立面 是一种能使病毒或木马免于被杀毒软件查杀的软件 它除了使病毒木马免于被查杀外 还可以扩增病毒木马的功能 改变病毒木马的行为 免杀的基本特征是破坏特征 有可能是行为特征 只要破坏了病毒与木马
  • Ubuntu18.04 编译安装llvm-clang

    背景知识 LLVM和GCC的区别 传统编译器 传统编译器的工作原理基本上都是三段式的 可以分为前端 Frontend 优化器 Optimizer 后端 Backend 前端负责解析源代码 检查语法错误 并将其翻译为抽象的语法树 Abstra