偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

什么是LLVM?Swift, Rust, Clang等語言背后的支持

開發(fā) 后端
要了解用于以編程方式生成機(jī)器原生代碼的編譯器框架是如何讓新語言的推出以及對現(xiàn)有的語言進(jìn)行增強(qiáng)比以往更加容易了。新的語言,還有對現(xiàn)有語言的提升,在整個(gè)編程環(huán)境中正大行其道。

要了解用于以編程方式生成機(jī)器原生代碼的編譯器框架是如何讓新語言的推出以及對現(xiàn)有的語言進(jìn)行增強(qiáng)比以往更加容易了。

新的語言,還有對現(xiàn)有語言的提升,在整個(gè)編程環(huán)境中正大行其道。Mozilla 的 Rust、Apple 的 Swift、Jetbrains 的 Kotlin,以及許多其它的語言都給開發(fā)者在速度、安全性、便利性、可移植性還有能力這些方面提供了新的選擇。

[[220551]]

為什么現(xiàn)在正當(dāng)時(shí)呢?一個(gè)大因素就是那些用來構(gòu)建語言的新工具,特別是編譯器。它們中首當(dāng)其沖就是 LLVM (底層虛擬機(jī) Low-Level Virtual Machine),這是一個(gè)開源項(xiàng)目,最開始作為伊利諾伊州大學(xué)的一個(gè)研究項(xiàng)目由 Swift 語言的創(chuàng)始人 Chris Lattner 進(jìn)行開發(fā)。

LLVM 使創(chuàng)建新語言變得更加容易,同時(shí)也可以增強(qiáng)現(xiàn)有語言的開發(fā)。它提供了一些工具,用于自動(dòng)執(zhí)行語言創(chuàng)建任務(wù)中最不討人喜歡的部分:創(chuàng)建一個(gè)編譯器,將輸出的代碼移植到多個(gè)平臺和架構(gòu),編寫代碼來處理常見的語言隱喻,比如異常。它的自由授權(quán)意味著它可以自由地作為軟件組件重用或作為服務(wù)部署。

使用 LLVM 的語言名冊中有許多熟悉的名字。蘋果的 Swift 語言使用 LLVM 作為它的編譯器框架,而 Rust 則將 LLVM 作為其工具鏈的核心組件。而且,許多編譯器都有一個(gè) LLVM 版本,如 Clang、C/C++ 編譯器(這個(gè)名稱叫做“C-lang”),它本身就是一個(gè)與 LLVM 緊密相連的項(xiàng)目。而 Kotlin,名義上是一種 JVM 語言,正在開發(fā)一種名為 Kotlin Native 的語言版本,它使用 LLVM 來編譯成機(jī)器原生代碼。

LLVM 定義

在它的核心,LLVM 是一個(gè)以編程方式創(chuàng)建機(jī)器原生代碼的庫。開發(fā)人員使用該 API 以一種稱為中間代理或 IR 的格式生成指令。然后 LLVM 可以將 IR 編譯成一個(gè)獨(dú)立的二進(jìn)制文件,或者在另一個(gè)程序(如語言解釋器)的上下文中執(zhí)行 JIT (just-in-time) 編譯。

LLVM 的 API 為開發(fā)在編程語言中發(fā)現(xiàn)的許多常見結(jié)構(gòu)和模式提供了原始的方式。例如,幾乎每種語言都有函數(shù)和全局變量的概念。LLVM 將函數(shù)和全局變量作為其 IR 中的標(biāo)準(zhǔn)元素,因此,你只需在意 LLVM 的實(shí)現(xiàn),并關(guān)注需要注意的語言部分,而不是花費(fèi)時(shí)間和精力重新創(chuàng)建這些特定的輪子。

 

這是一個(gè) LLVM 中間代理(IR)的例子。右邊是一個(gè)簡單的 C 程序;左邊是由 Clang 編譯器翻譯成 LLVM IR 的代碼。

LLVM:專為可移植性而生

關(guān)于 LLVM 的一個(gè)說法是它像常提到的 C 編程語言:C 語言有時(shí)候被認(rèn)為是一種便攜式、高級的匯編語言,因?yàn)樗梢跃o密地映射到系統(tǒng)硬件的結(jié)構(gòu),而且它已經(jīng)被移植到幾乎所有的系統(tǒng)架構(gòu)。但是,C 語言只是作為一種可移植的匯編語言,是其工作方式的另一種效果;這并不是它的設(shè)計(jì)目標(biāo)之一。

相比之下,LLVM 的 IR 是從一開始就設(shè)計(jì)為可移植的組件。它實(shí)現(xiàn)這種可移植性的一種方法是提供獨(dú)立于任何特定機(jī)器架構(gòu)的原語。例如,整數(shù)類型不局限于底層硬件的***位寬度(例如 32 或 64 位),您可以根據(jù)需要使用盡可能多的比特字節(jié)來創(chuàng)建基本的整數(shù)類型,比如 128 位整數(shù)。您也不必?fù)?dān)心手工輸出來匹配特定處理器的指令集;LLVM 也會(huì)為你處理這個(gè)問題。

如果你希望看到 LLVM IR 的現(xiàn)場示例,請?jiān)L問 ELLCC 項(xiàng)目網(wǎng)站,并嘗試在瀏覽器中將 C 代碼轉(zhuǎn)換為 LLVM IR 的現(xiàn)場演示 Demo。

編程語言中如何使用 LLVM

LLVM 最常見的用例是作為一種語言的預(yù)先(AOT ahead-of-time)編譯器。但 LLVM 也可以用于即時(shí)編譯。

用 LLVM 進(jìn)行即時(shí)編譯

有些情況下需要在運(yùn)行時(shí)動(dòng)態(tài)生成代碼,而不是預(yù)先編譯。例如,Julia 語言就是使用 JIT 編譯代碼,因?yàn)樗枰焖龠\(yùn)行,并通過 REPL(read-eval-print loop)或交互式提示與用戶交互。.Net 和 Mono 可以選擇通過 LLVM 后端方式編譯為原生代碼。

Numba 是一個(gè) Python 的數(shù)學(xué)加速包,JIT 將所選擇的 Python 函數(shù)編譯成機(jī)器碼。它也可以預(yù)先編譯使用 Numba 裝飾器裝飾的代碼,但是(比如 Julia)Python 作為一種快速發(fā)展的解釋性語言,使用 JIT 編譯來產(chǎn)生這樣的代碼更好地補(bǔ)充了 Python 的交互式工作流,比 Python 的預(yù)先編譯方式更好。

其他人正在嘗試以非正統(tǒng)方式使用 LLVM 作為 JIT 編譯方式,例如編譯 PostgreSQL 查詢,據(jù)說性能提高了五倍。

 

Numba 使用 LLVM 進(jìn)行即時(shí)編譯數(shù)字代碼并加速其執(zhí)行。JIT 加速過的 sum2d 函數(shù)的執(zhí)行速度比常規(guī) Python 代碼快 139 倍。

使用 LLVM 進(jìn)行自動(dòng)代碼優(yōu)化

LLVM 不僅將 IR 編譯為原生機(jī)器碼。你也可以直接以編程的方式在整個(gè)鏈接過程中高度精細(xì)地優(yōu)化代碼。優(yōu)化方式是相當(dāng)積極主動(dòng)的,能夠?qū)崿F(xiàn)包括內(nèi)聯(lián)函數(shù)在內(nèi),消除死代碼(包括未使用的類型聲明和函數(shù)參數(shù))和展開循環(huán)這些事情。

這里再一次強(qiáng)調(diào),LLVM 的力量讓你不必自己實(shí)現(xiàn)所有這一切。LLVM 可以為您處理它們,您也可以根據(jù)需要直接禁用。例如,如果你想要一些更小的二進(jìn)制代碼,那么你可以讓你的編譯器告訴 LLVM 禁用循環(huán)展開。

使用 LLVM 的領(lǐng)域特定語言

LLVM 已被用于生成多種通用語言的編譯器,但它也可用于生成高度垂直或排他性問題域的語言。從某種意義上說,這就是 LLVM 最閃光的地方,因?yàn)樗趧?chuàng)造這樣一類語言方面消除了諸多苦差事,并使其表現(xiàn)良好。

例如,Emscripten 項(xiàng)目采用 LLVM IR 代碼并將其轉(zhuǎn)換為 JavaScript,理論上支持使用 LLVM 作為后端的任何語言導(dǎo)出可在瀏覽器中運(yùn)行的代碼。長期規(guī)劃是支持基于 LLVM 的后端并能夠生成 WebAssembly 代碼,Emscripten 是 LLVM 靈活性的一個(gè)很好的例子。

LLVM 可以被使用的另一種方法是將特定領(lǐng)域的擴(kuò)展添加到現(xiàn)有語言。Nvidia 使用 LLVM 創(chuàng)建了 Nvidia CUDA 編譯器,該編譯器允許語言為 CUDA 添加原生支持,它是作為你生成的原生代碼的一部分編譯的,而不是通過附帶的庫進(jìn)行調(diào)用的。

在不同語言中使用 LLVM

使用 LLVM 的典型方式是通過你所熟悉的語言來編寫代碼(當(dāng)然也要有支持 LLVM 的庫)。

兩種常見的可選語言是 C 和 C++。許多 LLVM 開發(fā)者會(huì)因?yàn)橐韵碌脑蚨J(rèn)選擇其中的一個(gè):

  • LLVM 本身是用 C++ 編寫的
  • LLVM 的 API 以 C 和 C++ 版本提供
  • 大量的語言開發(fā)往往會(huì)以 C/C++ 作為一個(gè)基礎(chǔ)

不過,這兩種語言并不是唯一的選擇。許多語言都可以原生調(diào)用 C 語言庫,所以理論上可以用任何這樣的語言進(jìn)行 LLVM 開發(fā)。但需要有一個(gè)實(shí)際的語言庫可以很好地封裝 LLVM API。幸運(yùn)的是,許多語言和語言運(yùn)行時(shí)都有這樣的庫,包括 C#/.Net/Mono, Rust, Haskell, OCAML, Node.js, Go, 和 Python。

 

需要注意的是,一些與 LLVM 的語言綁定可能不完整。以 Python 為例,有很多種綁定選擇,但每個(gè)選項(xiàng)的完整性和實(shí)用性各不相同:

LLVM 項(xiàng)目維護(hù)著自己的一套到 LLVM 的 C API 的綁定,但是目前他們沒有繼續(xù)維護(hù)。

llvmpy 在 2015 年后就沒有進(jìn)行維護(hù)了 —— 這對于任何軟件項(xiàng)目都是不利的,在使用 LLVM 時(shí)更是如此,因?yàn)槊總€(gè)版本的 LLVM 都有一些變化。

由創(chuàng)建 Numba 的團(tuán)隊(duì)開發(fā)的 llvmlite 已經(jīng)成為當(dāng)前在 Python 中的 LLVM 的競爭者。它只實(shí)現(xiàn)了 LLVM 功能的一個(gè)子集,正如 Numba 項(xiàng)目的需求所規(guī)定的那樣。但是這個(gè)子集滿足了絕大多數(shù) LLVM 用戶所需。

llvmcpy 旨在為 C 庫帶來***的 Python 綁定,它以自動(dòng)化的方式保持更新,并使用 Python 的習(xí)慣用法來訪問它們。llvmcpy 還處于早期階段,但是已經(jīng)可以用 LLVM API 做一些基本的工作。

如果你對如何使用 LLVM 庫構(gòu)建語言感興趣,不妨看看 LLVM 的創(chuàng)建者撰寫的使用 C++ 或 OCAML 語言的教程,它將一步步指導(dǎo)你創(chuàng)建一種簡單的名為 Kaleidoscope 的語言。它還被移植到其他語言之上:

  • Haskell:參考原始教程的直接移植。
  • Python:在此網(wǎng)站的教程和原始版本非常相近,而另一個(gè)版本則是用交互式命令行進(jìn)行更為雄心勃勃的重寫。這兩種版本都使用 llvmlite 作為到 LLVM 的綁定。
  • Rust 和 Swift:不可避免地,我們不得不將該教程移植到這兩種語言之上,它們都是由 LLVM 自身幫助使其誕生的。

***,這個(gè)教程也有其他國家語言版本的。這里有中文版,分別是使用原始的 C++ 和 Python 版本。

LLVM 尚未實(shí)現(xiàn)的功能

了解 LLVM 可以實(shí)現(xiàn)的功能的同時(shí),有必要知道 LLVM 目前尚未實(shí)現(xiàn)的功能。

例如,LLVM 不解析語言的語法。因?yàn)槟壳耙呀?jīng)有許多工具實(shí)現(xiàn)這個(gè)功能,比如 lex/yacc, flex/bison,以及ANTLR。解析語法就意味著必須從編譯中解耦出來,難怪 LLVM 并沒有涉及這個(gè)領(lǐng)域。

LLVM 也不會(huì)直接干涉到開發(fā)語言的軟件文化,比如安裝編譯器的二進(jìn)制文件、如何在安裝中管理軟件包、升級工具鏈 —— 這些都需要開發(fā)者自己去實(shí)現(xiàn)。

***也是最重要的一點(diǎn)是,LLVM還沒有對部分通用語言成分給出原語。許多語言都具有某種垃圾回收的內(nèi)存管理方式,或者是作為管理內(nèi)存的主要方式,或者作為對 RAII ( C++ 底層實(shí)現(xiàn)的自動(dòng)垃圾回收,表面使用 Rust 語法)等策略的附屬方式。LLVM 并不會(huì)給你一個(gè)垃圾回收機(jī)制,但是它提供了實(shí)現(xiàn)垃圾回收的工具,它允許在代碼中使用元數(shù)據(jù)標(biāo)記,讓編寫垃圾回收器變得更加容易。

盡管如此,但是 LLVM 未來還有有可能添加原生的機(jī)制來實(shí)現(xiàn)垃圾回收機(jī)制。LLVM 正在快速發(fā)展中,大概 6 個(gè)月就會(huì)有一次大版本的更新。由于當(dāng)前的許多語言都使用 LLVM 作為開發(fā)的核心,因此 LLVM 的迭代速度只會(huì)更快而不會(huì)放慢。

責(zé)任編輯:未麗燕 來源: 開源中國編譯
相關(guān)推薦

2016-12-12 14:19:59

LLVMClangApple

2021-12-27 11:11:30

LLVMSPIR-V后端

2018-04-13 10:56:14

編譯器工具開發(fā)者

2021-04-25 18:09:53

Fedora 35編譯器開發(fā)

2020-11-03 10:32:22

編譯器工具代碼

2017-04-11 08:36:09

iOS編譯應(yīng)用

2023-06-01 19:24:16

2020-11-13 07:19:45

元編程模型Java

2022-03-02 09:49:14

Rust編程語言

2022-11-24 13:05:27

ClangiOS

2021-12-09 09:20:42

RustLinux內(nèi)核開發(fā)者

2015-12-04 10:05:09

蘋果編程開源

2024-05-06 09:26:06

Rust語言編碼

2022-03-27 23:11:39

Go語言函數(shù)

2021-01-14 15:49:10

Linux 5.12GCC編譯器

2024-02-22 10:17:39

AI模型

2016-01-29 09:38:03

編程swiftubuntu

2017-11-21 11:05:29

谷歌操作系統(tǒng)Swift

2021-03-23 14:50:16

編程語言Rust漏洞

2016-06-07 14:42:18

Swift設(shè)計(jì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號