LLVM Cpu0 新后端4

 想好好熟悉一下llvm开发一个新后端都要干什么,于是参考了老师的系列文章:

LLVM 后端实践笔记

代码在这里(还没来得及准备,先用网盘暂存一下):

链接: https://pan.baidu.com/s/1yLAtXs9XwtyEzYSlDCSlqw?pwd=vd6s 提取码: vd6s 

之前的章节只介绍了汇编代码生成的内容,这一章,我们将介绍对 ELF 目标格式文件的支持以及如何使用 objdump 工具来验证生成的目标文件。这一章的功能上的较复杂的代码其实不是很多,主要是框架上的东西。(因此这一章节参考原作者的内容较多)

当 llc 指定 -filetype=obj 时,编译器会生成目标文件(而不是汇编文件),此时,AsmPrinter::OutStreamer 所引用的是 MCObjectStreamer(汇编时引用的是 MCAsmStreamer)。LLVM 官方认为这个结构是后端代码生成阶段非常好的一个设计。

关键的一个接口是Cpu0AsmPrinter::EmitInstruction(),这个接口调用 MCObjectStreamer::EmitInstruction() ,进而根据选择生成的目标文件格式(ELF,COFF等)调用对应的编码发射函数,如 ELF 使用 MCELFStreamer()::EmitInstToData()。此时会进入到 Cpu0MCCodeEmitter.cpp 文件的实现中,调用 Cpu0MCCodeEmitter::encodeInstruction(),配合 TableGen 生成的 Cpu0MCCodeEmitter::getBinaryCodeForInstr()等接口完成最后的发射。

获取待发射指令编码的调用过程为:

Cpu0MCCodeEmitter::encodeInstruction()中,调用TableGen生成的 Cpu0GenMCCodeEmitter.inc 中的 getBinaryCodeForInstr(),传入 MI.Opcode; getBinaryCodeForInstr() 将 MI.Operand 传入 Cpu0MCCodeEmitter::getMachineOpValue() 来获取操作数的编码,这还需要再配合 Cpu0GenRegisterInfo.inc 和 Cpu0GenInstrInfo.inc 中的编码信息;getBinaryCodeForInstr() 将操作数的编码和指令操作码统一返回给 encodeInstruction();

比如一个加法操作,%0 = add %1, %2 生成为 adds $v0, $at, $v1,除了 adds 指令的编码需要在 Cpu0GenInstrInfo.inc 中查看外,还需要通过getEncodingValue(Reg) 到 Cpu0GenRegisterInfo.inc 中查看寄存器的编码,寄存器的编码和编码位置都在 Cpu0RegisterInfo.td 文件中描述了。

目录

1. 新增的文件

1.1 MCTargetDesc/Cpu0AsmBackend.cpp/.h

1.2 MCTargetDesc/Cpu0ELFObjectWriter.cpp

1.3 MCTargetDesc/Cpu0ELFStreamer.cpp/.h

1.4 MCTargetDesc/Cpu0FixupKinds.h

1.5 MCTargetDesc/Cpu0MCCodeEmitter.cpp/.h

1.6 MCTargetDesc/Cpu0MCExpr.cpp/.h

1.7 MCTargetDesc/Cpu0TargetStreamer.cpp/.h

2. 修改的文件

2.1 MCTargetDesc/Cpu0MCTargetDesc.cpp/.h


1. 新增的文件

1.1 MCTargetDesc/Cpu0AsmBackend.cpp/.h

比较重要的一个文件,实现了 Cpu0AsmBackend 类,继承自 MCAsmBackend 类。这个类作为汇编器后端实现类,目前对 Fixup 信息的操作提供了接口,比如 applyFixup() 用来使能 Fixup 状态,getFixupKindInfo() 用来获取 Fixup 类型信息,getNumFixupKinds() 用来获取 Fixup 类型的数量,mayNeedRelaxation() 返回需要 relaxation 的指令的状态(目前是空),fixupNeedsRelaxation() 返回给定 fixup 下的指令是否需要 relaxation 的状态(目前是空)。

已经定义了一些常用的 fixup 类型,比如 32 位类型:fixup_Cpu0_32, fixup_Cpu0_HI16, fixup_Cpu0_LO16,还有 GOT 的一些 fixup 类型。这些函数都是对基类函数的覆写,有关于重定向的功能都将在之后的章节讲解,所以目前会留空。我们还在其中实现了两个工厂函数,createCpu0AsmBackendEL32() 和 createCpu0AsmBackendEB32(),用来返回一个 AsmBackend 的实例。

1.2 MCTargetDesc/Cpu0ELFObjectWriter.cpp

定义了一个叫 Cpu0ELFObjectWriter 的类,继承自 MCELFObjectTargetWriter 类。这个类将用来完成最终的 ELF 文件格式的写入任务。其中提供了 getRelocType() 方法用来获取重定位类型,needsRelocateWithSymbol() 判断某种重定位类型是否是符号重定位,默认大多数都是符号重定位。

1.3 MCTargetDesc/Cpu0ELFStreamer.cpp/.h

定义了一个叫 Cpu0ELFStreamer 的类,继承自 MCELFStreamer 类。另外定义了这个类的工厂函数 createCpu0ELFStreamer(),用来返回其对象。ELFStreamer 对象会注册到后端模块中。TargetStreamer 和 ELFStreamer 在生成 ELF 文件中同时起作用,ELFStreamer 是我们自定义的一个类,在其中可以做一些改动来调整输出内容。目前这些文件中都还是比较空的状态,我们先搭建整个框架。

1.4 MCTargetDesc/Cpu0FixupKinds.h

这个头文件中定义了 llvm::Cpu0::Fixups 的枚举值,这里的定义顺序必须与Cpu0AsmBackend.cpp 中的 MCFixupKindInfo 保持一致。

1.5 MCTargetDesc/Cpu0MCCodeEmitter.cpp/.h

另一个比较重要的类,用来为Streamer类提供直接发射编码的实现接口。定义了比如 encodeInstruction() 等重要接口。我们在 encodeInstruction() 中检查一些未完成编码设计的指令,这还需要考虑一些特殊情况,比如要排除编码为 0 的情况,排除伪指令(伪代码不应该出现在这这个阶段了)。getBinaryCodeForInstr() 函数是 TableGen 自动生成的,可以通过传入给定的 MI 指令,获取该指令的编码。

1.6 MCTargetDesc/Cpu0MCExpr.cpp/.h

针对操作数是表达式的情况,我们需要额外做处理。其中定义了Cpu0MCExpr类,继承自 MCTargetExpr类。其中声明了表达式类型 Cpu0ExprKind,还提供了 create(), getKind() 等接口。

1.7 MCTargetDesc/Cpu0TargetStreamer.cpp/.h

定义了一个叫 Cpu0TargetStreamer 的类,继承自 MCTargetStreamer 类。定义了一个叫 Cpu0TargetAsmStreamer 的类,继承自 Cpu0TargetStreamer 类,这个类用来完成汇编器 Streamer 的功能。AsmStreamer 对象会注册到后端模块中。

2. 修改的文件

2.1 MCTargetDesc/Cpu0MCTargetDesc.cpp/.h

我们知道这个文件中会完成注册一些后端模块的功能。首先定义了两个函数,createMCStreamer() 调用 createCpu0ELFStreamer() 用来建立 ELFStreamer 对象,createCpu0AsmTargetStreamer() 直接建立 Cpu0TargetAsmStreamer 对象。

然后就是调用TargetRegistry::RegisterELFStreamer()和 TargetRegistry::RegisterAsmTargetStreamer()来注册这两个对象模块。另外,还调用 TargetRegistry::RegisterMCCodeEmitter() 来注册大小端的 MCCodeEmitter 对象,以及调用 TargetRegistry::RegisterMCAsmBackend() 来注册大小端的 MCAsmBackend 对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/696260.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构和算法之数组和链表

一、数组 数组是一种线性数据结构,它是由一组连续的内存单元组成的,用于存储相同类型的数据。在JavaScript中,数组可以包含任意类型的数据,不只限于基本数据类型。 1.存储方式 在内存中,数组的元素是连续存储的&…

芒果YOLOv10改进38:写作篇:一文了解YOLOv10如何打印FPS指标

只需订阅这一个专栏即可阅读:芒果YOLOv10所有改进内容 💡🚀🚀🚀本博客内含改进源代码,按步骤操作运行改进后的代码即可 💡更方便的统计更多实验数据,方便写作 新增YOLOv10打印FPS指标 完善(一键YOLOv10打印FPS指标) 文章目录 完善(一键YOLOv10打印FPS指标)YOLO…

欧美北美南美国外媒体投稿和东南亚中东亚洲媒体海外新闻发稿软文推广营销策略有哪些?

在当今全球化的浪潮中,中国品牌正积极拓展海外市场,寻求更广阔的发展空间。面对国际竞争,有效的海外媒体发稿营销策略对于品牌国际化至关重要。以下是一些关键点和建议,以帮助品牌在海外市场取得成功。 深入了解目标市场&#xf…

吴恩达神经网络学习笔记1

代码解释 并不是全部代码,思路的流程 import numpy as np# 如何判断咖啡豆是烤好了 # 假设此神经网络由2层构成###### 这部分代码只是如何建立2层网络, ###### 并不包含如何加载神经网络中的参数 w 和 b######################## 第1层网络# x 是…

运维小妙招:如何让系统信息随登录自动展现?

在日常运维工作中,及时获取系统的基本信息对于维护系统的稳定性和安全性至关重要。通过一个简单的登录脚本,我们可以在用户每次登录时自动显示系统的关键信息,这不仅提高了工作效率,还能快速定位问题。本文将介绍如何编写这样一个…

ELK组件

资源列表 操作系统 IP 主机名 Centos7 192.168.10.51 node1 Centos7 192.168.10.52 node2 部署ELK日志分析系统 时间同步 chronyc sources -v 添加hosts解析 cat >> /etc/hosts << EOF 192.168.10.51 node1 192.168.10.52 node2 EOF 部署Elasticsea…

双Token方案实现Token自动续期(基于springboot+vue前后端分离项目)

文章目录 前言一、双Token方案介绍1. 令牌类型与功能2.双Token方案的优点3.实现流程 二、具体实现1.后端实现1.1 jwt工具类1.2 响应工具类1.3 实体类1.4 过滤器1.5 controller1.6 启动类 2、前端实现2.1 登录页面2.2 index页面2.3 请求拦截器和响应拦截器 效果展示 前言 更多j…

rce漏洞试试看 buuctf的pingpingping 试试ctf的rce怎么样

打开靶机开始操作 然后我们先知道一些知识点&#xff1a;下面这些是常用的 |这个管道符也就是上一条的命令的输出结果作为下一条命令的输入&#xff1b;这个是跟sql的堆叠注入是一样的|| || 当前面的执行出错时&#xff08;为假&#xff09;执行后面的 & 将任务置于后台执…

基于pytoch卷积神经网络水质图像分类实战

具体怎么学习pytorch&#xff0c;看b站刘二大人的视频。 完整代码&#xff1a; import numpy as np import os from PIL import Image import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data…

模板显式、隐式实例化和(偏)特化、具体化的详细分析

最近看了<The C Programing Language>看到了模板的特化&#xff0c;突然想起来<C Primer>上说的显式具体化、隐式具体化、特化、偏特化、具体化等概念弄得头晕脑胀&#xff0c;我在网上了找了好多帖子&#xff0c;才把概念给理清楚。 看着这么多叫法&#xff0c;其…

晨控CK-UR12-E01与欧姆龙NX/NJ系列EtherNet/IP通讯手册

晨控CK-UR12-E01与欧姆龙NX/NJ系列EtherNet/IP通讯手册 晨控CK-UR12-E01 是天线一体式超高频读写器头&#xff0c;工作频率默认为902MHz&#xff5e;928MHz&#xff0c;符合EPC Global Class l Gen 2&#xff0f;IS0-18000-6C 标准&#xff0c;最大输出功率 33dBm。读卡器同时…

C语言怎样初始化图形模式?

一、问题 在C语⾔中&#xff0c;initgraph( ) 函数⽤于初始化图形模式。初始化时&#xff0c;那么多参数都是⼲什么的&#xff1f;怎样设置&#xff1f; 二、解答 initgraph( ) 函数⽤于初始化图形模式&#xff0c;其语法格式如下。 void far initgraph(int far * gdriver, i…

0基础学习区块链技术——入门

大纲 区块链构成区块链相关技术Hash算法区块链区块链交易 参考资料 本文力求简单&#xff0c;不讨论任何技术细节&#xff0c;只是从简单的组成来介绍区块链技术&#xff0c;以方便大家快速入门。同时借助一些可视化工具&#xff0c;辅助大家有直观的认识。 区块链构成 顾名思…

python导入非当前目录(如:父目录)下的内容

在开发python项目时&#xff0c;通常会划分不同的目录&#xff0c;甚至不同层级的目录&#xff0c;这时如果直接导入不在当前目录下的内容时&#xff0c;会报如下的错误&#xff1a;ModuleNotFoundError: No module named miniai其实这里跟操作系统的环境变量很类似的&#xff…

绘唐官网绘唐科技

绘唐AI工具是一种基于人工智能技术的绘画辅助工具。 使用教程&#xff1a;https://iimenvrieak.feishu.cn/docx/CWwldSUU2okj0wxmnA0cHOdjnF 它可以根据用户提供的输入或指令生成各种类型的图像。 绘唐AI工具可以理解用户的绘画需求&#xff0c;并根据用户的要求生成具有艺术…

文件操作(Python和C++版)

一、C版 程序运行时产生的数据都属于临时数据&#xff0c;程序—旦运行结束都会被释放通过文件可以将数据持久化 C中对文件操作需要包含头文件< fstream > 文件类型分为两种: 1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中 2. 二进制文件- 文件以文本的二进…

【图解IO与Netty系列】Netty核心组件解析

Netty核心组件解析 Bootstrap & ServerBootstrapEventLoop & EventLoopGroupChannelChannelHandler & ChannelPipeline & ChannelHandlerContextChannelHandlerChannelPipelineChannelHandlerContext ChannelFuture Bootstrap & ServerBootstrap Bootstra…

免费!GPT-4o发布,实时语音视频丝滑交互

We’re announcing GPT-4o, our new flagship model that can reason across audio, vision, and text in real time. 5月14日凌晨&#xff0c;OpenAI召开了春季发布会&#xff0c;发布会上公布了新一代旗舰型生成式人工智能大模型【GPT-4o】&#xff0c;并表示该模型对所有免费…

AI智能体做高考志愿填报分析

关注公众号&#xff0c;赠送AI/Python/Linux资料&#xff0c;对AI智能体有兴趣的朋友也可以添加一起交流 高考正在进行时&#xff0c;学生焦虑考试&#xff0c;家长们焦虑的则是高考志愿怎么填。毕竟一个好的学校&#xff0c;好的专业是进入社会的第一个敲门砖 你看张雪峰老师…