LLVM学习笔记(58)
4.4. 目标机器对象
在main()函数的350行,TimeCompilations默认为1,可以通过隐藏的选项“-time-compilations”来指定它的值,它的作用是重复进行指定次数的编译,以得到更好的编译用时数据。而在这个循环中调用的compileModule(),则是执行编译的入口。
387 static int compileModule(char **argv, LLVMContext &Context) {
388 // Load the module to be compiled...
389 SMDiagnostic Err;
390 std::unique_ptr<Module> M;
391 std::unique_ptr<MIRParser> MIR;
392 Triple TheTriple;
393
394 bool SkipModule = MCPU == "help" ||
395 (!MAttrs.empty() && MAttrs.front() == "help");
396
397 // If user just wants to list available options, skip module loading
398 if (!SkipModule) {
399 if (InputLanguage == "mir" ||
400 (InputLanguage == "" && StringRef(InputFilename).endswith_lower(".mir"))) {
401 MIR = createMIRParserFromFile(InputFilename, Err, Context);
402 if (MIR) {
403 M = MIR->parseIRModule();
404 } else
405 M = parseIRFile(InputFilename, Err, Context);
406 if (!M) {
407 Err.print(argv[0], errs() WithColor::error(errs(), argv[0]));
408 return 1;
409 }
410
411 // If we are supposed to override the target triple, do so now.
412 if (!TargetTriple.empty())
413 M->setTargetTriple(Triple::normalize(TargetTriple));
414 TheTriple = Triple(M->getTargetTriple());
415 } else {
416 TheTriple = Triple(Triple::normalize(TargetTriple));
417 }
418
419 if (TheTriple.getTriple().empty())
420 TheTriple.setTriple(sys::getDefaultTargetTriple());
421
422 // Get the target specific parser.
423 std::string Error;
424 const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
425 Error);
426 if (!TheTarget) {
427 errs() << argv[0] << ": " << Error;
428 return 1;
430 }
431
432 std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();
433
434 CodeGenOpt::Level OLvl = CodeGenOpt::Default;
435 switch (OptLevel) {
436 default:
437 errs() << argv[0] << ": invalid optimization level.\n";
438 return 1;
439 case ' ': break;
440 case '0': OLvl = CodeGenOpt::None; break;
441 case '1': OLvl = CodeGenOpt::Less; break;
442 case '2': OLvl = CodeGenOpt::Default; break;
443 case '3': OLvl = CodeGenOpt::Aggressive; break;
444 }
445
446 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
447 Options.DisableIntegratedAS = NoIntegratedAssembler;
448 Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
449 Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory;
450 Options.MCOptions.AsmVerbose = AsmVerbose;
451 Options.MCOptions.PreserveAsmComments = PreserveComments;
452 Options.MCOptions.IASSearchPaths = IncludeDirs;
453 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
398行的SkipModule不为true才会执行真正的编译。Llc编译的源文件有两种格式。一种是后缀为.mir的MIR文件。这种文件用于调试,可以用来测试单个代码生成遍,在Machine Instructions Format Reference有详细的介绍。另一种就是Clang生成的IR格式文件。这里都不深入解析输出文件生成Module对象的过程。Module实例是所有其他LLVM IR对象的顶层容器。每个Module对象直接包含这个模块所也依赖的一组全局变量,一组函数,一组库,一张符号表,及目标机器属性的各种数据。
412行的TargetTriple可以通过选项“-mtriple”来设置,缺省为空字符串,这时从输入文件得到的Module对象获取这个目标机器三位信息。如果还获取不了,在420行使用“i686-pc-linux-gnu”作为缺省选择。424行TargetRegistry::lookupTarget()在前面注册的Target对象里查找与TheTriple匹配的实例。445行InitTargetOptionsFromCodeGenFlags()根据命令行选项来设置TargetOptions对象。
下面467行的FloatABIForCalls来自编译选项-float-abi,这用于选择浮点的ABI类型,有default、soft、hard这3种选择。那么只要它不是default,就要把它记录在Options里。
下面的SplitDwarfOutputFile来自选项-split-dwarf-output,指定一个.dwo后缀的文件。通过在编译时刻把调试信息分为两部分——一部分保留在.o文件,另一部分写入一个并行的.dwo(DWARF目标)文件——可以减小由链接器处理的目标文件的总体尺寸。Out与DwoOut就是这两个文件。
DisableSimplifyLibCalls同样来自选项-disable-simplify-libcalls,用于禁止使用内置函数(builtin)。
LLVM IR本身在不断演进,为了向下兼容,v7.0提供更新功能,可以将过时的IR固有函数或特性更新到当前版本。下面的UpgradeDebugInfo()检查调试信息的版本,丢弃过时的调试信息。
compileModule(续)
454 std::unique_ptr<TargetMachine> Target(TheTarget->createTargetMachine(
455 TheTriple.getTriple(), CPUStr, FeaturesStr, Options, getRelocModel(),
456 getCodeModel(), OLvl));
457
458 assert(Target && "Could not allocate target machine!");
459
460 // If we don't have a module then just exit now. We do this down
461 // here since the CPU/Feature help is underneath the target machine
462 // creation.
463 if (SkipModule)
464 return 0;
465
466 assert(M && "Should have exited if we didn't have a module!");
467 if (FloatABIForCalls != FloatABI::Default)
468 Options.FloatABIType = FloatABIForCalls;
469
470 // Figure out where we are going to send the output.
471 std::unique_ptr<ToolOutputFile> Out =
472 GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
473 if (!Out) return 1;
474
475 std::unique_ptr<ToolOutputFile> DwoOut;
476 if (!SplitDwarfOutputFile.empty()) {
477 std::error_code EC;
478 DwoOut = llvm::make_unique<ToolOutputFile>(SplitDwarfOutputFile, EC,
479 sys::fs::F_None);
480 if (EC) {
481 WithColor::error(errs(), argv[0]) << EC.message() << '\n';
482 return 1;
483 }
484 }
485
486 // Build up all of the passes that we want to do to the module.
487 legacy::PassManager PM;
488
489 // Add an appropriate TargetLibraryInfo pass for the module's triple.
490 TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
491
492 // The -disable-simplify-libcalls flag actually disables all builtin optzns.
493 if (DisableSimplifyLibCalls)
494 TLII.disableAllFunctions();
495 PM.add(new TargetLibraryInfoWrapperPass(TLII));
496
497 // Add the target data from the target machine, if it exists, or the module.
498
499 M->setDataLayout(Target->createDataLayout());
500
501 // This needs to be done after setting datalayout since it calls verifier
502 // to check debug info whereas verifier relies on correct datalayout.
503 UpgradeDebugInfo(*M);
504
505 // Verify module immediately to catch problems before doInitialization() is
506 // called on any passes.
507 if (!NoVerify && verifyModule(*M, &errs())) {
508 std::string Prefix =
509 (Twine(argv[0]) + Twine(": ") + Twine(InputFilename)).str();
510 WithColor::error(errs(), Prefix) << "input module is broken!\n";
511 return 1;
512 }
上面的NoVerify则来自选项-disable-verify,用于禁止验证输入模块。因为LLVM可以接受IR形式的模块,我们需要一定的安全检查,确保模块是良好的。这个验证不提供完整的“Java形式的”安全与验证,相反只尝试保证代码是良好的,它会完成这些内容(来自文件verifier.cpp的注释):
- 二元操作符的参数都是相同类型
- 内存访问指令的索引与其他操作数相符
- 算术及其他仅在第一类类型上执行。偏转(shift)与逻辑操作仅发生在整数上。
- Switch语句里的所有常量都有正确的类型
- 代码是有效的SSA形式
- 在其他类型(比如结构体)里放置或返回标记(label)是非法的(除了常量数组)
- 只有phi节点可以援引自己:add i32 %0, %0 ; <int>:0是错误的
- 对每个前驱,phi必须仅有一个入口
- Phi节点必须是基本块里最先出现的,全部集中在一起
- Phi节点必须有至少一个入口
- 所有基本块应该以terminator指令结束,但不能包含它们
- 函数的入口节点必须没有前驱
- 所有指令必须嵌套在基本块里
- 函数不能接受void类型参数
- 函数实参列表必须与声明类型相符
- 为void值指定名字是非法的
- 没有初始化的内部全局值是非法的
- 返回与函数返回值类型不相符的值是非法的
- 函数调用实参类型与函数原型相符
- 降落点(landing pad,在异常发生后继续执行的地方)由landingpad指令定义,仅能从invoke指令的unwind边跳转过来
- Landingpad指令必须是块中第一条非PHI指令
- Landingpad指令必须在带有personality属性的函数中
- 其他所有被由分散在代码里断言测试的对象
454行调用下面的方法创建一个TargetMachine对象,这个对象是对目标机器的一个完整描述。
388 TargetMachine * createTargetMachine(StringRef TT, StringRef CPU,
389 StringRef Features,
390 const TargetOptions &Options,
391 Reloc::Model RM,
392 CodeModel::Model CM = None,
393 CodeGenOpt::Level OL = CodeGenOpt::Default,
394 bool JIT = false) const {
395 if (!TargetMachineCtorFn)
396 return nullptr;
397 return TargetMachineCtorFn(*this, Triple(TT), CPU, Features, Options, RM,
398 CM, OL, JIT);
399 }
397行的TargetMachineCtorFn就是前面注册的RegisterTargetMachine的Allocator(),调用它创建一个X86TargetMachine实例。
215 X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
216 StringRef CPU, StringRef FS,
217 const TargetOptions &Options,
218 Reloc::Model RM,
219 CodeModel::Model CM,
220 CodeGenOpt::Level OL, JIT)
221 : LLVMTargetMachine(
222 T, computeDataLayout(TT), TT, CPU, FS, Options,
223 getEffectiveRelocModel(TT, JIT, RM),
224 getEffectiveCodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL),
225 TLOF(createTLOF(getTargetTriple())) {
226 // Windows stack unwinder gets confused when execution flow "falls through"
227 // after a call to 'noreturn' function.
228 // To prevent that, we emit a trap for 'unreachable' IR instructions.
229 // (which on X86, happens to be the 'ud2' instruction)
230 // On PS4, the "return address" of a 'noreturn' call must still be within
231 // the calling function, and TrapUnreachable is an easy way to get that.
232 // The check here for 64-bit windows is a bit icky, but as we're unlikely
233 // to ever want to mix 32 and 64-bit windows code in a single module
234 // this should be fine.
235 if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() ||
236 TT.isOSBinFormatMachO()) {
237 this->Options.TrapUnreachable = true;
238 this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO();
239 }
240
241 // Outlining is available for x86-64.
242 if (TT.getArch() == Triple::x86_64)
243 setMachineOutliner(true);
244
245 initAsmInfo();
246 }
X86TargetMachine是LLVMTargetMachine的派生类。基类LLVMTargetMachine构造函数的定义是:
77 LLVMTargetMachine::LLVMTargetMachine(const Target &T,
78 StringRef DataLayoutString,
79 const Triple &TT, StringRef CPU,
80 StringRef FS, TargetOptions Options,
81 Reloc::Model RM, CodeModel::Model CM,
82 CodeGenOpt::Level OL)
83 : TargetMachine(T, DataLayoutString, TT, CPU, FS, Options) {
84 this->RM = RM;
85 this->CMModel = CM;
86 this->OptLevel = OL;
87
88 if (EnableTrapUnreachable)
89 this->Options.TrapUnreachable = true;
90 }
另外,基类TargetMachine的构造函数是这样的:
35 TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
36 const Triple &TT, StringRef CPU, StringRef FS,
37 const TargetOptions &Options)
38 : TheTarget(T), DL(DataLayoutString), TargetTriple(TT), TargetCPU(CPU),
39 TargetFS(FS), AsmInfo(nullptr), MRI(nullptr), MII(nullptr), STI(nullptr),
40 RequireStructuredCFG(false), DefaultOptions(Options), Options(Options) {
41 }
DefaultOptions与Options都被初始化为相同的内容。不过,由于不同的函数可以使用不同的属性,因此DefaultOptions保存了根据编译命令行设置的属性(对当前编译单元而言,所谓的缺省属性),而Options会根据当前函数声明使用的属性进行更新。
相关文章:
LLVM学习笔记(58)
4.4. 目标机器对象 在main()函数的350行,TimeCompilations默认为1,可以通过隐藏的选项“-time-compilations”来指定它的值,它的作用是重复进行指定次数的编译,以得到更好的编译用时数据。而在这个循环中调用的compileModule()&a…...
C语言 每日一题 PTA 10.30 day8
1.高空坠球 皮球从某给定高度自由落下,触地后反弹到原高度的一半,再落下,再反弹,……,如此反复。问皮球在第n次落地时,在空中一共经过多少距离?第n次反弹的高度是多少? 输入格式 : …...
nacos在linux中的安装、集群的配置、mysql生产配置
1.下载和安装 官方下载地址:https://github.com/alibaba/nacos/releases,根据自己需要的本版去下载就行 下载的是 .tar.gz 后缀的文件是linux版本的 使用tar命令解压,完成之后是一个nacos的文件夹 和windows下的文件夹目录是一样的 要启…...
OpenAI 组建安全 AGI 新团队!应对AI“潘多拉魔盒”
夕小瑶科技说 原创 作者 | 小戏 一旦谈及未来 AI,除了天马行空的科幻畅想,不可避免的也有未来 AI 时代的末日预言。从 AI 武器化到 AI 欺骗,从邪恶 AI 到 AI 掌权,人工智能,尤其是通用人工智能的风险始终都清清楚楚的…...
上网行为管理软件有哪些丨功能图文超详细介绍
很多人都在后台问,上网行为管理软件到底是什么,有什么作用,今天就重点给大家讲解一下: 是什么 上网行为管理软件可以帮助企业规范员工的上网行为,提高办公效率,减少潜在威胁。 有哪些 在市面上ÿ…...
DVWA-SQL Injection SQL注入
概念 SQL注入,是指将特殊构造的恶意SQL语句插入Web表单的输入或页面请求的查询字符串中,从而欺骗后端Web服务器以执行该恶意SQL语句。 成功的 SQL 注入漏洞可以从数据库中读取敏感数据、修改数据库数据(插入/更新/删除)、对数据…...
【0基础学Java第四课】-- 逻辑控制
4. 逻辑控制 4.1 顺序结构4.2 分支结构4.2.1 if语句判断一个数字是奇数还是偶数判断一个数字是正数,负数,还是零判断一个年份是否为闰年 4.2.2 switch 语句 4.3 while循环打印 1 - 10 的数字计算 1 - 100 的和计算 5 的阶乘计算1!2࿰…...
C++中的std::cout与std::cerr、std::clog
本文用于记录C中std::cout与std::cerr、std::clog的异同 std::cerr 是C标准库中的标准错误输出流,用于向标准错误设备输出信息,通常用于报告程序的错误和异常情况。与之相对的,std::cout 是标准输出流,用于向标准输出设备输出一般…...
No authorization token was found
今天遇到了一个问题,我把前后端逻辑都理了一遍,开始怀疑后端,后端肯定没错了,把前端理了一遍,ok前后端没错,我错。登录哪里需要的token????把我搞懵逼了。 测…...
Kubernetes概述及其组件/核心组件
目录 1、K8S 是什么? 2、为什么要用 K8S? 3、k8s的特性 4、Kubernetes 集群架构与组件 5、核心组件 Master 组件 ●Kube-apiserver ●Kube-controller-manager ●Kube-scheduler 配置存储中心 ●etcd Node 组件 ●Kubelet ●Kube-Proxy ●docker 或…...
毫米波雷达实时采集教
https://www.cnblogs.com/dhyc/p/10510876.html 毫米波雷达实时采集教程---- 以及好网站总结:资料分享——RSP1 多普勒雷达开发套件...
Java进阶(HashMap)——面试时HashMap常见问题解读 结合源码分析
前言 List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中HashMap集合的面试问题,结合源码分析题目背后的知识点。 关于List的博客文章如下: Java进阶(List)——面试…...
Kotlin 使用@BindingAdapter编译出错
在 Kotlin 中使用 BindingAdapter 注解时,需要确保你的项目正确配置了 Data Binding。 首先,请确保在项目的 build.gradle 文件中启用了 Data Binding: android {// ...dataBinding {enabled true} }接下来,请确保你在正确的地…...
Qt之信号和槽,connect参数分析
connect()方法 Qt进行信号和槽连接,有以下几种方法: static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType Qt::AutoConnection); static QMetaObj…...
Python学习笔记—元组
1、元组定义 元组使用()来定义,元素在()括号内,用逗号隔开 空元组定义,元组名() 注:当元组只有1个元素的时候,需要在元素后面加逗号,…...
【C++项目】高并发内存池第五讲内存回收释放过程介绍
内存回收 1.ThreadCache2.CentralCache3.PageCache 项目源代码:高并发内存池 1.ThreadCache void ThreadCache::Deallocate(void* ptr, size_t size) {assert(ptr);assert(size < MAX_BYTES);//计算在哪号桶中,然后插入进去size_t index SizeClass…...
[毕设记录]@学术工具体验:Sread.ai
我是在查RAG相关的时候,在知乎上面看到了这篇回答:浅谈生成式 AI 技术:检索增强生成 RAG - MarvinZ的文章 - 知乎 https://zhuanlan.zhihu.com/p/659248219 然后在末尾看到了这个 sread.ai 在作者主页看到了他关于这个产品的介绍:…...
uboot - 驱动开发 - 驱动模型
说明 类似于linux,为了规范、统一驱动适配和驱动接口调用,uboot定义了一套驱动模型(Driver Model),简称DM。本文基于:u-boot-2021.10。 优点 为同一类ip的驱动定义了统一的操作接口,DM在软件层面做了一定的抽象。分…...
windows 操作系统命令积累
1. 按 "prt sc" 键 截屏 2. 按 "fn" 键让浏览器进入全屏模式,再次按 "fn" 键让浏览器退出全屏模式( ps:惠普笔记本上是 "fn" "f11" ) 3. ipconfig 查看ip信息 4. 查看指定端口被什么进程占用...
数据结构单链表的实现(C语言)
目录 1.实现的接口和功能2.代码块 1.实现的接口和功能 //打印链表 void SLTPrint(SLTNode** phead); //头插 void PushFont(SLTNode** phead, SLTDataType x); //尾插 void PushBack(SLTNode** phead, SLTDataType x); //头删 void PopFont(SLTNode** phead); //尾删 void Pop…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
