什么是 LLVM?Swift, Rust, Clang 等语言背后的原力

   2023-02-09 学习力0
核心提示:点击上方“iOS开发”,选择“置顶公众号”关键时刻,第一时间送达!创造新的语言,变着花样的提升现有语言的能力,这在整个编程界正风行。Mozilla 的 Rust、Apple 的 Swift、Jetbrains 的 Kotlin,以及许多其它的语言都给开发者在速度、安全性、便利性、可移

点击上方“iOS开发”,选择“置顶公众号”

关键时刻,第一时间送达!

什么是 LLVM?Swift, Rust, Clang 等语言背后的原力

什么是 LLVM?Swift, Rust, Clang 等语言背后的原力


创造新的语言,变着花样的提升现有语言的能力,这在整个编程界正风行。Mozilla 的 RustApple 的 SwiftJetbrains 的 Kotlin,以及许多其它的语言都给开发者在速度、安全性、便利性、可移植性还有能力这些方面提供了新的选择。


为什么现在正当时呢?一个大因素就是那些用来构建语言的新工具,特别是编译器。它们中首当其冲就是 LLVM (底层虚拟机 Low-Level Virtual Machine),这是一个开源项目,最开始作为伊利诺伊州大学的一个研究项目由 Swift 语言的创始人 Chris Lattner 进行开发。


LLVM 使创建新语言变得更加容易,同时也可以增强现有语言的开发。它提供了一些工具,用于自动执行语言创建任务中最不讨人喜欢的部分:创建一个编译器,将输出的代码移植到多个平台和架构,编写代码来处理常见的语言隐喻,比如异常。它的***授权意味着它可以***地作为软件组件重用或作为服务部署。


使用 LLVM 的语言名册中有许多熟悉的名字。苹果的 Swift 语言使用 LLVM 作为它的编译器框架,而 Rust 则将 LLVM 作为其工具链的核心组件。而且,许多编译器都有一个 LLVM 版本,如 Clang、C/C++ 编译器(这个名称叫做“C-lang”),它本身就是一个与 LLVM 紧密相连的项目。而 Kotlin,名义上是一种 JVM 语言,正在开发一种名为 Kotlin Native 的语言版本,它使用 LLVM 来编译成机器原生代码。


LLVM 定义


在它的核心,LLVM 是一个以编程方式创建机器原生代码的库。开发人员使用该 API 以一种称为中间代理或 IR 的格式生成指令。然后 LLVM 可以将 IR 编译成一个独立的二进制文件,或者在另一个程序(如语言解释器)的上下文中执行 JIT (just-in-time) 编译。


LLVM 的 API 为开发在编程语言中发现的许多常见结构和模式提供了原始的方式。例如,几乎每种语言都有函数和全局变量的概念。LLVM 将函数和全局变量作为其 IR 中的标准元素,因此,你只需在意 LLVM 的实现,并关注需要注意的语言部分,而不是花费时间和精力重新创建这些特定的***。


什么是 LLVM?Swift, Rust, Clang 等语言背后的原力


这是一个 LLVM 中间代理(IR)的例子。右边是一个简单的 C 程序;左边是由 Clang 编译器翻译成 LLVM IR 的代码。


LLVM:专为可移植性而生


关于 LLVM 的一个说法是它像常提到的 C 编程语言:C 语言有时候被认为是一种便携式、高级的汇编语言,因为它可以紧密地映射到系统硬件的结构,而且它已经被移植到几乎所有的系统架构。但是,C 语言只是作为一种可移植的汇编语言,是其工作方式的另一种效果;这并不是它的设计目标之一。


相比之下,LLVM 的 IR 是从一开始就设计为可移植的组件。它实现这种可移植性的一种方法是提供独立于任何特定机器架构的原语。例如,整数类型不局限于底层硬件的最大位宽度(例如 32 或 64 位),您可以根据需要使用尽可能多的比特字节来创建基本的整数类型,比如 128 位整数。您也不必担心手工输出来匹配特定处理器的指令集;LLVM 也会为你处理这个问题。


如果你希望看到 LLVM IR 的现场示例,请访问 ELLCC 项目网站,并尝试在浏览器中将 C 代码转换为 LLVM IR 的现场演示 Demo。


编程语言中如何使用 LLVM


LLVM 最常见的用例是作为一种语言的预先(AOT ahead-of-time)编译器。但 LLVM 也可以用于即时编译。


用 LLVM 进行即时编译


有些情况下需要在运行时动态生成代码,而不是预先编译。例如,Julia 语言就是使用 JIT 编译代码,因为它需要快速运行,并通过 REPL(read-eval-print loop)或交互式提示与用户交互。.Net 和 Mono 可以选择通过 LLVM 后端方式编译为原生代码。


Numba 是一个 Python 的数学加速包,JIT 将所选择的 Python 函数编译成机器码。它也可以预先编译使用 Numba 装饰器装饰的代码,但是(比如 Julia)Python 作为一种快速发展的解释性语言,使用 JIT 编译来产生这样的代码更好地补充了 Python 的交互式工作流,比 Python 的预先编译方式更好。


其他人正在尝试以非正统方式使用 LLVM 作为 JIT 编译方式,例如编译 PostgreSQL 查询,据说性能提高了五倍。


什么是 LLVM?Swift, Rust, Clang 等语言背后的原力


Numba 使用 LLVM 进行即时编译数字代码并加速其执行。JIT 加速过的 sum2d 函数的执行速度比常规 Python 代码快 139 倍。


使用 LLVM 进行自动代码优化


LLVM 不仅将 IR 编译为原生机器码。你也可以直接以编程的方式在整个链接过程中高度精细地优化代码。优化方式是相当积极主动的,能够实现包括内联函数在内,消除死代码(包括未使用的类型声明和函数参数)和展开循环这些事情。


这里再一次强调,LLVM 的力量让你不必自己实现所有这一切。LLVM 可以为您处理它们,您也可以根据需要直接禁用。例如,如果你想要一些更小的二进制代码,那么你可以让你的编译器告诉 LLVM 禁用循环展开。


使用 LLVM 的领域特定语言


LLVM 已被用于生成多种通用语言的编译器,但它也可用于生成高度垂直或排他性问题域的语言。从某种意义上说,这就是 LLVM 最闪光的地方,因为它在创造这样一类语言方面消除了诸多苦差事,并使其表现良好。


例如,Emscripten 项目采用 LLVM IR 代码并将其转换为 JavaScript,理论上支持使用 LLVM 作为后端的任何语言导出可在浏览器中运行的代码。长期规划是支持基于 LLVM 的后端并能够生成 WebAssembly 代码,Emscripten 是 LLVM 灵活性的一个很好的例子。


LLVM 可以被使用的另一种方法是将特定领域的扩展添加到现有语言。Nvidia 使用 LLVM 创建了 Nvidia CUDA 编译器,该编译器允许语言为 CUDA 添加原生支持,它是作为你生成的原生代码的一部分编译的,而不是通过附带的库进行调用的。


在不同语言中使用 LLVM


使用 LLVM 的典型方式是通过你所熟悉的语言来编写代码(当然也要有支持 LLVM 的库)。


两种常见的可选语言是 C 和 C++。许多 LLVM 开发者会因为以下的原因而默认选择其中的一个:


  1. LLVM 本身是用 C++ 编写的

  2. LLVM 的 API 以 C 和 C++ 版本提供

  3. 大量的语言开发往往会以 C/C++ 作为一个基础


不过,这两种语言并不是唯一的选择。许多语言都可以原生调用 C 语言库,所以理论上可以用任何这样的语言进行 LLVM 开发。但需要有一个实际的语言库可以很好地封装 LLVM API。幸运的是,许多语言和语言运行时都有这样的库,包括 C#/.Net/Mono, Rust, Haskell, OCAML, Node.js, Go, 和 Python


需要注意的是,一些与 LLVM 的语言绑定可能不完整。以 Python 为例,有很多种绑定选择,但每个选项的完整性和实用性各不相同:


  1. LLVM 项目维护着自己的一套到 LLVM 的 C API 的绑定,但是目前他们没有继续维护。

  2. llvmpy 在 2015 年后就没有进行维护了 —— 这对于任何软件项目都是不利的,在使用 LLVM 时更是如此,因为每个版本的 LLVM 都有一些变化。

  3. 由创建 Numba 的团队开发的 llvmlite 已经成为当前在 Python 中的 LLVM 的竞争者。它只实现了 LLVM 功能的一个子集,正如 Numba 项目的需求所规定的那样。但是这个子集满足了绝大多数 LLVM 用户所需。

  4. llvmcpy 旨在为 C 库带来最新的 Python 绑定,它以自动化的方式保持更新,并使用 Python 的习惯用法来访问它们。llvmcpy 还处于早期阶段,但是已经可以用 LLVM API 做一些基本的工作。


如果你对如何使用 LLVM 库构建语言感兴趣,不妨看看 LLVM 的创建者撰写的使用 C++ 或 OCAML 语言的教程,它将一步步指导你创建一种简单的名为 Kaleidoscope 的语言。它还被移植到其他语言之上:


  1. Haskell:参考原始教程的直接移植。

  2. Python:在此网站的教程和原始版本非常相近,而另一个版本则是用交互式命令行进行更为雄心勃勃的重写。这两种版本都使用 llvmlite 作为到 LLVM 的绑定。

  3. RustSwift:不可避免地,我们不得不将该教程移植到这两种语言之上,它们都是由 LLVM 自身帮助使其诞生的。


最后,这个教程也有其他国家语言版本的。这里有中文版,分别是使用原始的 C++ 和 Python 版本。


LLVM 尚未实现的功能


了解 LLVM 可以实现的功能的同时,有必要知道 LLVM 目前尚未实现的功能。


例如,LLVM 不解析语言的语法。因为目前已经有许多工具实现这个功能,比如 lex/yacc, flex/bison,以及ANTLR。解析语法就意味着必须从编译中解耦出来,难怪 LLVM 并没有涉及这个领域。


LLVM 也不会直接干涉到开发语言的软件文化,比如安装编译器的二进制文件、如何在安装中管理软件包、升级工具链 —— 这些都需要开发者自己去实现。


最后也是最重要的一点是,LLVM还没有对部分通用语言成分给出原语。许多语言都具有某种垃圾回收的内存管理方式,或者是作为管理内存的主要方式,或者作为对 RAII ( C++ 底层实现的自动垃圾回收,表面使用 Rust 语法)等策略的附属方式。LLVM 并不会给你一个垃圾回收机制,但是它提供了实现垃圾回收的工具,它允许在代码中使用元数据标记,让编写垃圾回收器变得更加容易。


尽管如此,但是 LLVM 未来还有有可能添加原生的机制来实现垃圾回收机制。LLVM 正在快速发展中,大概 6 个月就会有一次大版本的更新。由于当前的许多语言都使用 LLVM 作为开发的核心,因此 LLVM 的迭代速度只会更快而不会放慢。


什么是 LLVM?Swift, Rust, Clang 等语言背后的原力

  • 作者: 程序师 

  • 链接:http://www.techug.com/post/llvm-the-power-behind-swift-rust-clang-and-more.html

  • iOS开发整理发布,转载请联系作者授权

什么是 LLVM?Swift, Rust, Clang 等语言背后的原力

什么是 LLVM?Swift, Rust, Clang 等语言背后的原力【点击成为Java大神】

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • bloom-server 基于 rust 编写的 rest api cache 中间件
    bloom-server 基于 rust 编写的 rest api cache
    bloom-server 基于 rust 编写的 rest api cache 中间件,他位于lb 与api worker 之间,使用redis 作为缓存内容存储, 我们需要做的就是配置proxy,同时他使用基于share 的概念,进行cache 的分布存储,包含了请求端口(proxy,访问数据) 以及cache 控制端口(
    03-08
  • #新闻拍一拍# Oracle 调研如何避免让 Java 开发者投奔 Rust 和 Kotlin | Linux 中国
    #新闻拍一拍# Oracle 调研如何避免让 Java 开发
     导读:• 英特尔对迟迟不被 Linux 主线接受的 SGX Enclave 进行了第 38 次修订 • ARM 支持开源的 Panfrost Gallium3D 驱动本文字数:977,阅读时长大约:1分钟作者:硬核老王Oracle 调研如何避免让 Java 开发者投奔 Rust 和 KotlinOracle 委托分析公司 Omd
    03-08
  • Linux系统下Rust快速安装:国内镜像加速
    Linux系统下Rust快速安装:国内镜像加速
    官方网址和方法Install Rust - Rust Programming Language然而速度慢得让人难以置信。利用国内镜像进行windows的Linux子系统的Rust安装。rust 使用国内镜像,快速安装方法参考:RUST安装慢怎么办,使用镜像方式安装_网络_为中华之崛起而编程-CSDN博客我的操作
    03-08
  • Rust到底值不值得学--Rust对比、特色和理念
    前言其实我一直弄不明白一点,那就是计算机技术的发展,是让这个世界变得简单了,还是变得更复杂了。当然这只是一个玩笑,可别把这个问题当真。然而对于IT从业者来说,这可不是一个玩笑。几乎每一次的技术发展,都让这个生态变得更为复杂。“英年早秃”已经成
    03-08
  • 超33000行新代码,为Linux内核添加Rust支持的补丁已准备就绪
    超33000行新代码,为Linux内核添加Rust支持的补
    https://mp.weixin.qq.com/s/oKw9aBJSdmRoO6-rbLAkNw7 月 4 日,一套修订后的补丁被提交至 Linux 内核的邮件列表中,该补丁为在 Linux 内核中以 Rust 作为辅助编程语言提供了支持,借助 Rust 可以提高 Linux 内核和内存的安全。整套补丁包含 17 个子项,不光
    03-08
  • 【译】Rust 的 Result 类型入门
    【译】Rust 的 Result 类型入门
    A Primer on Rust’s Result Type 译文原文链接:https://medium.com/@JoeKreydt/a-primer-on-rusts-result-type-66363cf18e6a原文作者:Joe Kreydt译文出处:https://github.com/suhanyujie/article-transfer-rs译者:suhanyujietips:水平有限,翻译不当之
    03-08
  • Rust实战系列-基本语法
    Rust实战系列-基本语法
    主要介绍 Rust 的语法、基本类型和数据结构,通过实现一个简单版 grep 命令行工具,来理解 Rust 独有的特性。本文是《Rust in action》学习总结系列的第二部分,更多内容请看已发布文章:一、Rust实战系列-Rust介绍“主要介绍 Rust 的语法、基本类型和数据结
    03-08
  • 全栈程序员的新玩具Rust(三)板条箱
    上次用到了stdout,这次我们来写一个更复杂一点的游戏rust的标准库叫做std,默认就会引入。这次我们要用到一个随机数函数,而随机数比较尴尬的一点是这玩意不在标准库中,我们要额外依赖一个库。很多编程方案都有自己的模块化库系统,rust也不例外,不过rust
    02-10
  • 全栈程序员的新玩具Rust(六)第一个WASM程序
    全栈程序员的新玩具Rust(六)第一个WASM程序
    先上代码https://gitee.com/lightsever/rust_study/tree/master/wasm_hello01webassembly就不用再赘述了,耳朵里面快磨出茧子来了。rustwasm是火狐自家的玩具,让我们来继续做实验,让rust飞起来吧。环境安装安装好rust环境之后仍然需要 一个 wasm 工具包carg
    02-10
  • 【Rust】标准库-Result rust数据库
    环境Rust 1.56.1VSCode 1.61.2概念参考:https://doc.rust-lang.org/stable/rust-by-example/std/result.html示例main.rsmod checked {#[derive(Debug)]pub enum MathError {DivisionByZero,NonPositiveLogarithm,NegativeSquareRoot,}pub type MathResult =
    02-09
点击排行