基于LLVM的Fortran编译器分析

news2024/11/18 11:30:49

简介

本文内容基于LLVM 13.0.0。

目前基于LLVM的Fortran编译器(或者驱动)有3种,分别是flang、f18和flang-new。

flangpgfortran的开源版本,基于PGI/NVIDIA的商业Fortran 编译器,它并不从属于LLVM项目。NVIDIA团队在2018年宣布了Fortran的新前端——f18,f18是使用现代 C++ 从头开始​​编写的,它将与 LLVM 最佳实践紧密结合,并以 LLVM 和 clang 的风格编写,f18已经被纳入为LLVM子项目。flang-new是一款新的flang驱动,在未来将会取代f18驱动。flang-new目前没有实现Fortran程序从源码生成.out的完整过程,f18可以生成.out,但是是借助外部编译器来完成的,默认外部编译器为gfortran。

以下表格展示了f18和flang-new在编译器驱动和前端驱动的细分,编译器驱动程序将允许您控制所有编译阶段(即预处理、前端代码生成、中间/后端代码优化和降级、链接),前端驱动程序将所有前端库粘​​合在一起,并为前端提供易于使用且直观的接口。

Compiler driver

Frontend driver

f18

f18

f18

flang-new

flang-new

flang-new -fc1

在前端驱动方面,flang-new -fc1和f18完全兼容,在编译器驱动方面,flang-new尚不支持代码生成(code-generate),f18调用一个独立的外部Fortran编译器来生成代码。

编译安装

flang

根据github上的介绍,安装flang需要下载flang项目(https://github.com/flang-compiler/flang)和定制的LLVM项目(https://github.com/flang-compiler/classic-flang-llvm-project)。

编译时,先用gcc编译安装定制的LLVM,再用生成的clang编译安装libpgmath库和flang。编译LLVM时,需要把clang和openmp都装上,因为flang需要使用到openmp库。

编译安装成功后,flang相关的可执行文件也放在LLVM的bin目录下,其中flang1负责输出PGI IR,flang2负责输出LLVM IR。

f18&flang-new

宏FLANG_BUILD_NEW_DRIVER控制是否需要安装flang-new,默认为on,flang-new依赖于clang驱动,所以在安装flang-new的时候也需要安装clang,通过LLVM_ENABLE_PROJECTS把clang设置上,如果FLANG_BUILD_NEW_DRIVER设置为off,则不需要安装clang。

在f18被移除之后,宏FLANG_BUILD_NEW_DRIVER也会被一并删除,这意味着接下来LLVM中flang驱动对clang的依赖将是必须和永久的。

cmake -G "Unix Makefiles" 
-DLLVM_ENABLE_PROJECTS='clang;flang' 
-DCMAKE_INSTALL_PREFIX=../x86_tools 
-DCMAKE_BUILD_TYPE=Release 
-DLLVM_TARGETS_TO_BUILD=X86 
../llvm

编译安装成功后在bin目录下生成了以下两个flang驱动——f18和flang-new:

图中的flang并不是独立的可执行文件,不能通过gdb被调试,目前在使用时会被扩展为f18,在未来会根据FLANG_BUILD_NEW_DRIVER的设置被扩展为flang-new,同样地,flang_fc1被扩展为flang-new -fc1。

原理介绍

flang

flang在PGI Fortran编译器的基础之上,新增了将PGI中间表示转换为LLVM中间表示的能力,并提供了PGI Fortran的运行时,有了LLVM中间表示后就可以利用起LLVM的后端功能,从而进一步生成二进制文件。可以说,flang也是借助了外部编译器来完成Fortran的编译。

如前文所述,flang1负责输出PGI IR,flang2负责输出LLVM IR。flang1包含以下阶段:

1.扫描提取文本token

2.创建语法树和符号表

3.转换ASTcanonical为AST

4.将一般AST转换为优化的AST

5.创建AST ILM文件,即PGI IR1

flang2包含以下阶段:

1.ILM扩展为ILI文件,即PGI IR2

2.优化ILI文件

3.将ILI优化为LLVM IR

flang-new

编译阶段说明

官方文档表明flang编译分为以下8个阶段:

1.预扫描和预处理

flang-new -fc1 -E src.f90

这一阶段与一般的编译器的预处理阶段是一致的,操作包括宏替换、删除空格和注释等。

2.解析

flang-new -fc1 -fdebug-dump-parse-tree src.f90

将第1步中的输出转储为解析树

flang-new -fc1 -fdebug-unparse src.f90

将解析树转换为标准的Fortran源码

3.验证标签并规范化Do语句

4.解析名称

flang-new -fc1 -fdebug-dump-symbols src.f90

5.检查DO CONCURRENT约束

6.编写模块文件

7.分析表达式和任务

8.生成中间表示

实际上,由于开发尚未完成,目前的f18和flang-new还不能生成LLVM中间表示。

编译器驱动

flang-new的编译器驱动的主入口点的实现在flang/tools/flang-driver/driver.cpp中,它是基于clang的驱动库来实现的,这样的好处在于以下2点:

1. 受益于clang对各种目标、平台和操作系统的支持

2. 利用clang驱动LLVM中各种后端以及链接器、汇编器能力,所有的flang驱动器选项和clang的选项都定义在clang/include/clang/Driver/Options.td里,对于两者通用的选项,定义是同等共享的。

基于clangDriver的编译器驱动通过创建跟大量编译阶段相关的动作(action)来工作,比如clang::driver::Action::ActionClass枚举里定义的 PreprocessJobClassCompileJobClassBackendJobClass LinkJobClassLinkJobClass以及一些比较特殊的不直接映射到常见编译步骤的动作,比如MigrateJobClassInputClass。具体运行哪个动作,由编译选项决定,比如:

  1. -E表示PreprocessJobClass
  2. -c表示CompileJobClass

在大多数情况下,驱动会创建一个关于动作(action)/任务(job)/阶段(phase)的链(chain)来串起整个流程,可以使用-ccc-print-phases选项打印出驱动器为当前编译所生成的序列:

flang-new -ccc-print-phases -c file.f

         +- 0: input, "file.f", f95-cpp-input

      +- 1: preprocessor, {0}, f95

   +- 2: compiler, {1}, ir

+- 3: backend, {2}, assembler

4: assembler, {3}, object

前端驱动

flang-new的前端驱动程序是用户和flang前端之间的主要接口,主入口点fc1_mainflang/tools/flang-driver/driver.cpp里实现,通过flang-new -fc1访问。前端驱动程序一次只会运行一个动作(action),如果指定多个操作选项,则仅最后一个有效。

源码分析

flang

在编译安装后的bin目录中可以看到flang可执行文件是指向clang的,所以当执行flang时,main函数进的是clang的driver.cpp(clang/tools/driver/driver.cpp),通过以下代码解析当前需要使用flang:

auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);

此时的TargetAndMode打印出来为:

$1 = {TargetPrefix = "", ModeSuffix = "flang", DriverMode = 0x118ea194 "--driver-mode=flang", TargetIsValid = false}

与常规clang驱动流程的不同之处在于,flang会使用ClassicFlang.cpp中的ConstructJob()函数来组装flang的任务,该函数中指定了一系列调flang1和flang2所需要的参数和宏等内容,然后添加任务。

……

const char *UpperExec = Args.MakeArgString(getToolChain().GetProgramPath("flang1"));

……

C.addCommand(std::make_unique<Command>(JA, *this, UpperExec, UpperCmdArgs, Inputs));

const char *UpperExec = Args.MakeArgString(getToolChain().GetProgramPath("flang2"));

……

C.addCommand(std::make_unique<Command>(JA, *this, UpperExec, UpperCmdArgs, Inputs));

有了上面两个任务,Driver会调到以下函数逐个执行:

void Compilation::ExecuteJobs(const JobList &Jobs,

                              FailingCommandList &FailingCommands) const {

  // According to UNIX standard, driver need to continue compiling all the

  // inputs on the command line even one of them failed.

  // In all but CLMode, execute all the jobs unless the necessary inputs for the

  // job is missing due to previous failures.

  for (const auto &Job : Jobs) {

    if (!InputsOk(Job, FailingCommands))

      continue;

    const Command *FailingCommand = nullptr;

    if (int Res = ExecuteCommand(Job, FailingCommand)) {

      FailingCommands.push_back(std::make_pair(Res, FailingCommand));

      // Bail as soon as one command fails in cl driver mode.

      if (TheDriver.IsCLMode())

        return;

    }

  }

}

最终会传递给llvm::sys::ExecuteAndWait()函数。

return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,

                                   /*secondsToWait*/ 0,

                                   /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);

完整调用栈如下图所示,flang1和flang2是完全一致的。

f18

f18的main函数在flang/tools/f18/f18.cpp中,在main函数中通过F18_FC环境变量确定了外部Fortran编译器,对参数做了一系列准备后,通过Link()->Exec()最终调到llvm/lib/Support/Program.cpp中的llvm::sys::ExecuteAndWait()函数实现程序的执行。未来f18.cpp将会被移除,与之相关的代码也将被更新或删除。

int main(int argc, char *const argv[]) {

  atexit(CleanUpAtExit);



  DriverOptions driver;

  const char *F18_FC{getenv("F18_FC")};

  driver.F18_FCArgs.push_back(F18_FC ? F18_FC : "gfortran");

  bool isPGF90{driver.F18_FCArgs.back().rfind("pgf90") != std::string::npos};

……

  if (!driver.compileOnly && !objlist.empty()) {

    Link(liblist, objlist, driver);

  }

  return exitStatus;

}

flang-new

flang-new没有调用外部Fortran编译器,而是自己组织action,同样也是调到llvm::sys::ExecuteAndWait()函数实现程序的执行,但由于尚未开发完成,在ExecuteAction()的时候直接报错。

void EmitObjAction::ExecuteAction() {

  CompilerInstance &ci = this->instance();

  unsigned DiagID = ci.diagnostics().getCustomDiagID(

      clang::DiagnosticsEngine::Error, "code-generation is not available yet");

  ci.diagnostics().Report(DiagID);

}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW编程LabVIEW开发 ADAM 4015热电阻输入模块例程与相关资料

LabVIEW编程LabVIEW开发 ADAM 4015热电阻输入模块例程与相关资料 ​研华公司的ADAM 4015是6通道热电阻输入模块&#xff0c;可以采集2线或3线热电阻输入信号&#xff0c;ADAM4015T课题采集热敏电阻的输入信号。模块在工业测量和监控的有着广泛的应用&#xff0c;它既可以支持A…

Web3中文|苹果想对以太坊征税

虽然Web3是非常新的技术&#xff0c;但是似乎已经遇到了非常多“劲敌”。 这些“敌人”正在阻碍web3应用程序和区块链游戏的发展&#xff0c;因为在web3里&#xff0c;应用程序和游戏将允许用户自主相互交易数字资产所有权。 所以&#xff0c;那些大公司&#xff0c;如任天堂…

最近全网爆火的黑科技,叫做chatGPT

AI神器ChatGPT 火了。 能直接生成代码、会自动修复bug、在线问诊、模仿莎士比亚风格写作……各种话题都能hold住&#xff0c;它就是OpenAI刚刚推出的——ChatGPT。 有脑洞大开的网友甚至用它来设计游戏&#xff1a;先用ChatGPT生成游戏设定&#xff0c;再用Midjourney出图&…

vue 数据手写分页,定时展示

我们在业务之中&#xff0c;其实会常常用到一些数据的分段展示 &#xff0c; 比如数据量过大导致echarts无法展示&#xff0c;我们就可以将数据进行算法分页 &#xff0c; 然后套用定时器实时更新分段数据&#xff1b; 例子展示 &#xff1a; 将下列数组截取成每页5条数据的分…

观察者模式(python)

一、模式定义 1.观察者模式(Observer Pattern)&#xff1a;定义对象间的一种一对多依赖关系&#xff0c;使得每当一个对象状态发生改变时&#xff0c;其相关依赖对象皆得到通知并被自动更新。 2.观察者模式又叫做发布-订阅&#xff08;Publish/Subscribe&#xff09;模式、模…

SpringBoot微服务的发布与部署(3种方式)

基于 SpringBoot 的微服务开发完成之后&#xff0c;现在到了把它们发布并部署到相应的环境去运行的时候了。 SpringBoot 框架只提供了一套基于可执行 jar 包&#xff08;executable jar&#xff09;格式的标准发布形式&#xff0c;但并没有对部署做过多的界定&#xff0c;而且…

2022年Python面试题汇总【面试官爱问】

2022年Python面试题汇总【常问】1、请你讲讲python获取输入的方式&#xff0c;以及python如何打开文件2、Python数据处理的常用函数3、请你说说python传参传引用4、请你说说python和java的区别5、Python你常用的包有哪些&#xff1f;6、简单说明如何选择正确的Python版本。7、简…

Qt动态库

QT带界面的动态库 创建动态库 一、新建一个C的动态库的项目 选择C的动态库的项目&#xff0c;进行下一步 修改项目的名字和项目的保存的路径。 选着编译的方式&#xff0c;不需要改&#xff0c;进行下一步。 选着动态库&#xff0c;编译成动态库&#xff0c;进行下一步。 项目…

[附源码]JAVA毕业设计社区生活超市管理系统(系统+LW)

[附源码]JAVA毕业设计社区生活超市管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

[附源码]Python计算机毕业设计SSM计算机学院课程设计管理系统(程序+LW)

[附源码]Python计算机毕业设计SSM计算机学院课程设计管理系统&#xff08;程序LW) 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。…

基于安卓的课程管理系统app设计

目 录 第1章 绪论 1 1.1 什么是电子课程管理 1 1.2 系统开发的背景 1 1.3 本文主要工作 1 1.4 系统设计目标分析 2 第2章 基本技术方案 3 2.1 Android概述 3 2.2 Android系统的四大组件 3 2.3 Android中的相关技术介绍及分析 5 2.3.1 Android系统架构研究 5 2.3.2 Android架构分…

LeetCode 167. 两数之和 II - 输入有序数组

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 167. 两数之和 II - 输入有序数组&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称…

2.zookeeper

1.工作机制 从设计模式角度来理解&#xff1a;是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它负责存储和管理大家都关心的数据&#xff0c;然后接受观察者的注册&#xff0c;一旦这些数据的状态发生变化&#xff0c;Zookeeper就将负责通知已经在Zookeeper上注册…

p2.第一章 基础入门 -- 冯诺依曼体系和计算机基础 (二)

1.2 核心基础 1.2.1 计算机基础知识 艾伦麦席森图灵&#xff08;Alan Mathison Turing&#xff0c;1912年6月23日&#xff0d;1954年6月7日&#xff09;&#xff0c;英国数学家、逻辑学家&#xff0c;被称为计算机科学之父&#xff0c;人工智能之父。 图灵提出的著名的图灵机模…

铺瓷砖问题

1、题目 用 121 \times 212 的瓷砖&#xff0c;把 N2N \times 2N2 的区域填满&#xff0c;返回铺瓷砖的方法数。 2、思路 记录 F(n) 表示空的 n∗2n * 2n∗2 区域的铺瓷砖方法数。 如果第一块瓷砖 A 竖着放&#xff0c;则问题就变成了 F(n−1)F(n-1)F(n−1) 即空的 (n−1)∗…

C++习题3

求余运算符% 位运算&#xff08;<< >> & | ! ^ 左右移位&#xff0c;与&#xff0c;或&#xff0c;非 &#xff0c;异或&#xff09; 这些符号的运算对象都是整型 unsigned short x0xffff cout<<x; cout输出的是整数&#xff0c;所以要将16进制…

基于jsp+ssm的员工人事工资管理系统-计算机毕业设计

项目介绍 本系统是基于JSP的人事管理系统&#xff0c;使用java来实现动态管理以及数据库管理系统采用mysql等共同来完成。管理员可以通过人事管理系统进行工资管理、用户管理、员工考勤管理、部门管理、权限管理等。经理用户则可通过人事管理系统对进行工资管理、考勤管理、部…

快速排序(看完就会)

目录 什么是快速排序 快速排序的步骤&#xff1a; 以上&#xff1a; 图片步骤简绘&#xff1a; 代码实现&#xff1a; 什么是快速排序 快速排序是由C.A.R.Hoare在1960年提出。它的基本思想是&#xff1a;通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部…

easypoi导出excel,列要求是数字导出是文本的问题~并分析源码

&#x1f4c3;目录跳转&#x1f4da;简介&#xff1a;实体类分析源码效果&#x1f4da;简介&#xff1a; 由于使用了easypoi导出的excel列需要是数字的但是导出的默认是文本类型&#xff0c;这样选择列就无法进行统计求和&#xff0c;由于没有认真看注解导致我跑去分析源码。所…

ssm校园兼职系统|求职招聘系统计算机专业毕业论文java毕业设计开题报告

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 《ssm校园兼职系统》该项目采用技术&#xff1a;jsp springmvcspringmybatis cssjs等相关技术&#xff0c;项目含有源码、文档、配套开发软件、软…