創造新的語言,變着花樣的提升現有語言的能力,這在整個編程界正風行,其中首當其衝就是 LLVM (底層虛擬機 Low-Level Virtual Machine)。LLVM 使創建新語言變得更加容易,同時也可以增強現有語言的開發。
※ 什麼是LLVM?
LLVM 是一個以編程方式創建機器原生代碼的庫。開發人員使用該 API 以一種稱為中間代理或 IR 的格式生成指令。然後 LLVM 可以將 IR 編譯成一個獨立的二進制文件,或者在另一個程序(如語言解釋器)的上下文中執行 JIT (just-in-time) 編譯。
※ LLVM的特點:專為可移植性而生
很多人覺得LLVM與 C 編程語言很相似,但C 語言只是作為一種可移植的彙編語言,是其工作方式的一種效果,而非它的設計目標之一。
相比之下,LLVM 的 IR 是從一開始就設計為可移植的組件,能實現這種可移植性的一種方法是提供獨立於任何特定機器架構的原語。
※ 編程語言中如何使用 LLVM
1)用 LLVM 進行即時編譯
有些情況下,程序是需要在運行時動態生成代碼,而不是預先編譯,而.Net 和 Mono 等可以選擇通過 LLVM 後端方式編譯為原生代碼或即時編譯數字代碼並加速其執行。
2)使用 LLVM 進行自動代碼優化
LLVM 不僅將 IR 編譯為原生機器碼,還能直接以編程的方式在整個鏈接過程中高度精細地優化代碼。優化方式是相當積極主動的,能夠實現包括內聯函數在內,消除死代碼(包括未使用的類型聲明和函數參數)和展開循環這些事情。
3)使用 LLVM 的領域特定語言
LLVM 已被用於生成多種通用語言的編譯器,但它也可用於生成高度垂直或排他性問題域的語言。另外,LLVM 可以被使用的另一種方法是將特定領域的擴展添加到現有語言。
※ 在不同語言中使用 LLVM
使用 LLVM 的典型方式是通過你所熟悉的語言來編寫代碼,例如: C 和 C++,但這兩種語言並不是唯一的選擇。很多語言都都可以原生調用 C 語言庫,所以理論上可以用任何這樣的語言進行 LLVM 開發,但需要有一個實際的語言庫可以很好地封裝 LLVM API。
幸運的是,許多語言和語言運行時都有這樣的庫,包括 C#/.Net/Mono, Rust, Haskell, OCAML, Node.js, Go, 和 Python。需要注意的是,一些與 LLVM 的語言綁定可能不完整。
那麼, LLVM 還被移植到哪些語言之上呢?
Haskell:參考原始教程的直接移植。
Python:在此網站的教程和原始版本非常相近,而另一個版本則是用交互式命令行進行更為雄心勃勃的重寫。這兩種版本都使用 llvmlite 作為到 LLVM 的綁定。
Rust 和 Swift:不可避免地,我們不得不將該教程移植到這兩種語言之上,它們都是由 LLVM 自身幫助使其誕生的。
※ LLVM 尚未實現的功能
1)LLVM 不解析語言的語法
因為目前已經有許多工具實現這個功能,比如 lex/yacc, flex/bison,以及ANTLR。解析語法就意味着必須從編譯中解耦出來,因此 LLVM 並沒有涉及這個領域。
2)LLVM不會直接干涉到開發語言的軟件文化
比如安裝編譯器的二進制文件、如何在安裝中管理軟件包、升級工具鏈 —— 這些都需要開發者自己去實現。
3)LLVM還沒有對部分通用語言成分給出原語。
許多語言都具有某種垃圾回收的內存管理方式,或者是作為管理內存的主要方式,或者作為對 RAII ( C++ 底層實現的自動垃圾回收,表面使用 Rust 語法)等策略的附屬方式。LLVM 並不會給你一個垃圾回收機制,但是它提供了實現垃圾回收的工具,它允許在代碼中使用元數據標記,讓編寫垃圾回收器變得更加容易。
儘管如此,但是 LLVM 未來還有有可能添加原生的機制來實現垃圾回收機制。
現在,LLVM 正在快速發展中,大概6個月就會有一次大版本的更新,加上許多語言都使用 LLVM 作為開發的核心,因此 LLVM 的迭代速度只會更快而不會放慢。