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

ucosiii源码分析笔记 pdf下载_方舟编译器学习笔记14 DriverRunner源码分析

学习笔记12和学习笔记13,分析了phase相关的内容,基本理清了phase管理体系。但是,还有一个和phase有关的内容,那就是DriverRunner,本文就DriverRunner进行简单的分析和介绍。

官方文档“方舟编译器phase设计介绍”中,提到“使用者除了可以使用上面的方式自行添加phase外,还可以借助InterleavedManager和DriverRunner组成的框架对phase进行更有效的管理。”,我们在前文中也进行过分析,InterleavedManager对phase的管理,并没有绕开phase manager,而是基于phase manager进行实现的。

DriverRunner包含了从一个mpl文件到优化结果文件的所有过程。那么DriverRunner所要做的就像其名字所传递的直接含义,是一个驱动和运行的这么一个角色,它所要驱动的内容包含了一系列的phase,这些phase是从mpl文件到优化结果文件的过程总所必不可少的。现在对其主要的几个方法做介绍和分析。(DriverRunner的源码位于src/maple_driver/include/driver_runner.h和src/maple_driver/src/driver_runner.cpp)

1、DriverRunner的ParseInput方法负责解析mpl文件,这是为了后续的mpl2mpl做准备工作,也就是为了phase的工作做铺垫。

bool DriverRunner::ParseInput(std::string outputFile, std::string originBaseName) const {
  CHECK_MODULE(1);

  LogInfo::MapleLogger() << "Starting parse input" << std::endl;
  MPLTimer timer;
  timer.Start();

  MIRParser parser(*theModule);
  bool parsed = parser.ParseMIR(0, 0, false, true);
  if (!parsed) {
    parser.EmitError(outputFile);
  }
  timer.Stop();
  LogInfo::MapleLogger() << "Parse consumed " << timer.Elapsed() << "s" << std::endl;

  return parsed;
}

从代码中看出来这是使用了MIRParser 的ParseMIR方法进行分析。

2、ProcessMpl2mplAndMePhases方法通过InterleavedManager负责phase的管理和运行。所以,其可以被视为是基于InterleavedManager进行的管理,这种情况下就相当于在我们之前的管理上加上了一层,变成了一个四级管理体系: DriverRunner->InterleavedManager->PhaseManager->Phase。

void DriverRunner::ProcessMpl2mplAndMePhases(std::string outputFile, std::string vtableImplFile) const {
  CHECK_MODULE();

  if (mpl2mplOptions || meOptions) {
    LogInfo::MapleLogger() << "Processing mpl2mpl&mplme" << std::endl;
    MPLTimer timer;
    timer.Start();

    InterleavedManager mgr(optMp, theModule, meInput, timePhases);
    std::vector<std::string> phases;
#include "phases.def"
    InitPhases(mgr, phases);
    mgr.Run();

    theModule->Emit(vtableImplFile);

    timer.Stop();
    LogInfo::MapleLogger() << "Mpl2mpl&mplme consumed " << timer.Elapsed() << "s" << std::endl;
  }
}

另外,这里在InitPass之前,有一个

#include "phases.def"

这个文件位于src/maple_driver/defs/目录之下,其中包含了DriverRunner所要用的一系列phase,具体内容如下:

ADD_PHASE("classhierarchy", true)
ADD_PHASE("vtableanalysis", true)
ADD_PHASE("reflectionanalysis", true)
ADD_PHASE("gencheckcast", true)
ADD_PHASE("javaintrnlowering", true)
// mephase begin
ADD_PHASE("ssatab", true)
ADD_PHASE("aliasclass", true)
ADD_PHASE("ssa", true)
ADD_PHASE("analyzerc", true)
ADD_PHASE("rclowering", true)
ADD_PHASE("emit", true)
// mephase end
ADD_PHASE("GenNativeStubFunc", true)
ADD_PHASE("clinit", true)
ADD_PHASE("VtableImpl", true)
ADD_PHASE("javaehlower", true)
ADD_PHASE("MUIDReplacement", true)

中间一部分,是我们之前提到的从MeFuncPhase继承来的phase,这里的phase的列表,是me_phases.def中的子集,也就是说me_phases.def并没有都用在从一个mpl文件到优化结果文件的过程中。剩下的phase都是从ModulePhase继承而来的phase,正好module_phases.def的phase对的上。但是需要说明的是这些phase的定位位置都不同,可能是和其具体做的事情有关,后续会专门撰文分析。

3、InitPhases方法被ProcessMpl2mplAndMePhases方法调用,它会将添加的phase拆解到InterleavedManager的phase manager集合里。

void DriverRunner::InitPhases(InterleavedManager &mgr, std::vector<std::string> &phases) const {
  if (phases.empty()) {
    return;
  }

  const PhaseManager *curManager = nullptr;
  std::vector<std::string> curPhases;

  for (std::string phase : phases) {
    auto temp = mgr.GetSupportPhaseManager(phase);

    if (temp != nullptr) {
      if (temp != curManager) {
        AddPhases(mgr, curPhases, curManager);
        curManager = temp;
        curPhases.clear();
      }

      AddPhase(curPhases, phase, curManager);
    }
  }

  AddPhases(mgr, curPhases, curManager);
}

这里以两种不同的形式调用了AddPhases。下文会做介绍。

4、DriverRunner的InitPhases调用了AddPhases和AddPhase方法。(具体内容参见:

小乖他爹:方舟编译器学习笔记50 方舟编译器phase的体系运行机制分析)

void DriverRunner::AddPhases(InterleavedManager &mgr, std::vector<std::string> &phases,
                             const PhaseManager *phaseManager) const {
  if (phaseManager == nullptr) {
    return;
  }

  if (typeid(*phaseManager) == typeid(ModulePhaseManager)) {
    mgr.AddPhases(phases, true, timePhases);
  } else if (typeid(*phaseManager) == typeid(MeFuncPhaseManager)) {
    mgr.AddPhases(phases, false, timePhases, genMemPl);
  } else {
    CHECK_FATAL(false, "Should not reach here, phases should be handled");
  }
}

void DriverRunner::AddPhase(std::vector<std::string> &phases, std::string phase,
                            const PhaseManager *phaseManager) const {
  CHECK_FATAL(phaseManager != nullptr, "Invalid phase manager");

  if (typeid(*phaseManager) == typeid(ModulePhaseManager)) {
    if (mpl2mplOptions && Options::skipPhase.compare(phase) != 0) {
      phases.push_back(phase);
    }
  } else if (typeid(*phaseManager) == typeid(MeFuncPhaseManager)) {
    if (meOptions && meOptions->GetSkipPhases().find(phase) == meOptions->GetSkipPhases().end()) {
      phases.push_back(phase);
    }
  } else {
    CHECK_FATAL(false, "Should not reach here, phase should be handled");
  }
}

5、上述的几个重要方法,第1个方法ParseInput是为phase的使用做准备;第2个方法ProcessMpl2mplAndMePhases调用了第3个方法InitPhases;第3个InitPhases方法对第4个方法AddPhases进行了调用。而第一个方法ParseInput和第2个方法ProcessMpl2mplAndMePhases都是被方法Run所调用的。所以,我们上述说了这么多,所有的工作都已经统一到了Run方法中。

int DriverRunner::Run() {
  CHECK_MODULE(1);

  if (exeNames.empty()) {
    LogInfo::MapleLogger() << "Fatal error: no exe specified" << std::endl;
    return 1;
  }

  int ret = 0;
  printOutExe = exeNames[exeNames.size() - 1];

  // Prepare output file
  std::string::size_type lastdot = actualInput.find_last_of(".");
  std::string baseName = lastdot == std::string::npos ? actualInput : actualInput.substr(0, lastdot);
  std::string originBaseName = baseName;
  std::string outputFile = baseName.append(GetPostfix());

  bool parsed = ParseInput(outputFile, originBaseName);

  if (parsed) {
    if (mpl2mplOptions || meOptions) {
      std::string vtableImplFile = originBaseName;
      vtableImplFile.append(".VtableImpl.mpl");
      originBaseName.append(".VtableImpl");
      ProcessMpl2mplAndMePhases(outputFile, vtableImplFile);
    }

  } else {
    ret = 1;
  }

  return ret;
}

因为我们最近一直在讨论phase,而Run方法又是Phase类的重要方法,所以看到Run方法的第一反应就是DriverRunner类和Phase等一系列类有什么继承关系,其实并没有,这样的结构体系相对就清楚多了:

class DriverRunner final {

上述内容基本上将DriverRunner所要做的工作做了简要介绍,并结合代码对其主要方法都做了介绍。在这个过程中发现,两大类Phase的具体实现位置,并不统一,而是分散在多个目录,可能是跟其具体的功能有关,后续会有针对性的分析。另外,DriverRunner在整个编译过程中的使用,也还要进一步的去分析。

————————

今天中秋节,在此祝各位中秋佳节快乐!

——————更新记录————————

20191020:根据小乖他爹:方舟编译器学习笔记50 方舟编译器phase的体系运行机制分析更新了关于AddPhases和AddPhase的内容,之前的内容有错误。

相关文章:

  • wxWidgets在windows VC++下的安装
  • python serial_浅谈python中的多线程和多进程
  • StatCVS 对使用CVS的项目进行深入统计的开源工具
  • 2020无人用的邮箱和密码大全_2020年之微波炉怎么用 微波炉使用注意事项大全
  • 用C原生API写Symbian日志文件
  • go make function_Go中复制文件的3种技巧
  • 猪猪宝贝
  • 简述python文件操作_Python文件操作的几个要点与示例
  • 读书小结
  • tomcat线程被打满怎么排查_Tomcat面试题(2020最新版)
  • oc引导开机直接进_超级详细的oc引导制作过程(二)——config.plist的制作,从入门到入土...
  • 2007年你需要知道的五大技术
  • python中reader_关于Python 的这几个技巧,你应该知道
  • SVN时代...
  • sift算法双向匹配剔除不匹配点_【动手学计算机视觉】第七讲:传统目标检测之SIFT特征...
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • interface和setter,getter
  • JAVA并发编程--1.基础概念
  • PHP 小技巧
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • vue-loader 源码解析系列之 selector
  • 从重复到重用
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 分布式熔断降级平台aegis
  • 回顾2016
  • 算法---两个栈实现一个队列
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • !!java web学习笔记(一到五)
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • (6)设计一个TimeMap
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (第27天)Oracle 数据泵转换分区表
  • (二)hibernate配置管理
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (算法)Game
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET BackgroundWorker
  • .net CHARTING图表控件下载地址
  • .NET Remoting学习笔记(三)信道
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • .NET命名规范和开发约定
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @DataRedisTest测试redis从未如此丝滑
  • []新浪博客如何插入代码(其他博客应该也可以)
  • [14]内置对象
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法
  • [C]编译和预处理详解