当前位置: 首页 > news >正文

llvm后端之函数栈帧

llvm后端之函数栈帧

  • 引言
  • 1 目标扩展实现
    • 1.1 emitPrologue和emitEpilogue
    • 1.2 storeRegToStackSlot和loadRegFromStackSlot
  • 2 寄存器存栈与恢复

引言

llvm后端在物理寄存器分配后、指令发射前会调用PEI这个pass来生成函数栈帧的创建与销毁。

1 目标扩展实现

在target下,需要实现如下两个方法:

  • TargetFrameLowering子类重写emitPrologue与emitEpilogue方法;
  • TargetInstrInfo子类重写storeRegToStackSlot和loadRegFromStackSlot方法。

1.1 emitPrologue和emitEpilogue

TargetFrameLowering类的emitPrologue与emitEpilogue方法用于创建和消耗函数栈帧实现。以RISCV为例:

emitPrologue其核心逻辑如下:

  • 基于对齐考虑,调用RISCVFrameLowering::determineFrameLayout调整栈大小;
  • 若栈指针寄存器SPReg被引用,则报错退出;否则继续;
  • 若栈指针需要通过多次调整,则将临时变量StackSize设置为第一次调整的大小。这是通过getFirstSPAdjustAmount计算的;
  • 通过adjustReg生成扩展栈空间的指令。由于栈向下生长,是加上负StackSize大小;此外,该指令是插入到基本块最前端;
  • 将插入指令的迭代器位置往后移需要保存的寄存器的个数;
  • 通过adjustReg调整帧指针FPReg的位置,使其指向变长参数所在位置。若无变长参数,则FPReg则指向父函数调用本函数时的栈指针位置;
  • 如果getFirstSPAdjustAmount返回非0,则需要第二次扩展栈空间;
  • 如果TargetRegisterInfo::needsStackRealignment返回要求改函数需要比正常调用约定更严格的栈对齐,则对栈指针SPReg再向下扩展MaxAlignment长度;

注:此外源码中还有包括生成用于栈回溯的cfi指令。

emitEpilogue其核心逻辑如下:

  • 首先将插入指令的位置MBBI设置为基本块末尾;
  • 调整指令插入位置。若有终止指令,将MBBI指向第一个终止指令的前面,否则指向最后一个非终止且非debug指令的后面;
  • 如果栈指针SPReg在emitPrologue中做了多次调整,则需要反序恢复回来。前面的恢复指令插入位置是MBBI向前移动该函数作为被调用者需要保存的寄存器个数;最后一次插入位置是MBBI

1.2 storeRegToStackSlot和loadRegFromStackSlot

TargetInstrInfo类的storeRegToStackSlot和loadRegFromStackSlot方法用于寄存器压栈和出栈指令的生成。同样,以RISCV为例:

  • storeRegToStackSlot则是根据寄存器分类获取不同的压栈指令类型,例如在32位目标下的GPR寄存器类,则是sw指令;
  • loadRegFromStackSlot也是根据寄存器分类获取不同的出栈指令类型,例如在32位目标下的GPR寄存器类,则是lw指令;

2 寄存器存栈与恢复

细心的朋友可能会发现之前的代码逻辑缺失了寄存器的保留与恢复操作。这部分指令是在PEI这个pass中完成的,该pass是在TargetPassConfig::addMachinePasses中完成添加的。在PEI::runOnMachineFunction中:

  • 首先就调用PEI::spillCalleeSavedRegs生成了该函数作为被调用者需要保护寄存器的保留与恢复指令操作,其中包括调用XXXInstrInfo实现的storeRegToStackSlot和loadRegFromStackSlot方法;
  • 后续,调用PEI::insertPrologEpilogCode生成栈帧的创建与销毁指令。

注:由于提前生成保留寄存器的压栈与出栈指令,所以目标在实现emitPrologue和emitEpilogue方法时,需要注意指令的插入位置。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Mastering openFrameworks_第五章_使用视频
  • 健身管理|基于java的健身管理系统小程序(源码+数据库+文档)
  • 清理.svn文件夹执行命令bat
  • -isystem isystem 实验记录
  • 【数据结构与算法 | 灵神题单 | 前后指针(链表)篇】力扣19, 61,1721
  • 赛氪技术支持中医药知识大赛,亮相中国国际服务贸易交易会
  • 1997-2022年各省农用化肥折纯量数据(无缺失)
  • 【Kubernetes】常见面试题汇总(十五)
  • 数据库系统概论(3,4)
  • JDK8的一些主要的新特性
  • 计算机网络(第8版)第三章 数据链路层(3.4)
  • 【C++ Primer Plus习题】16.1
  • Azure web app has no access to openai private endpoint in virtual network
  • AttackGen - AI 网络安全事件响应测试工具,附下载链接
  • 【系统架构师】-论文-2024-2009年系统架构师历年论文题目
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • gcc介绍及安装
  • gulp 教程
  • HTTP--网络协议分层,http历史(二)
  • Js基础知识(四) - js运行原理与机制
  • Linux下的乱码问题
  • MYSQL 的 IF 函数
  • orm2 中文文档 3.1 模型属性
  • React组件设计模式(一)
  • Redux 中间件分析
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • XForms - 更强大的Form
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ### RabbitMQ五种工作模式:
  • #控制台大学课堂点名问题_课堂随机点名
  • (10)ATF MMU转换表
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (C++20) consteval立即函数
  • (二)Linux——Linux常用指令
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (七)Java对象在Hibernate持久化层的状态
  • (四)进入MySQL 【事务】
  • (一)Neo4j下载安装以及初次使用
  • (转)c++ std::pair 与 std::make
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • .gitignore
  • .NET HttpWebRequest、WebClient、HttpClient
  • .Net 基于.Net8开发的一个Asp.Net Core Webapi小型易用框架
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET关于 跳过SSL中遇到的问题
  • .NET企业级应用架构设计系列之技术选型
  • @html.ActionLink的几种参数格式
  • @RequestMapping用法详解
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [Angular 基础] - 表单:响应式表单
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配
  • [C#]OpenCvSharp 实现Bitmap和Mat的格式相互转换