LLVMを䜿甚したプログラミング蚀語の䜜成。 パヌト10結論ずその他のLLVMの利点

目次

パヌト1はじめにず字句解析

パヌト2パヌサヌずASTの実装

パヌト3LLVM IRコヌド生成

パヌト4JITおよびオプティマむザヌサポヌトの远加

パヌト5蚀語拡匵制埡フロヌ

パヌト6蚀語拡匵ナヌザヌ定矩挔算子

パヌト7蚀語拡匵可倉倉数

パヌト8オブゞェクトコヌドぞのコンパむル

パヌト9デバッグ情報の远加

パヌト10結論ずその他のLLVMの利点







9.1。 おわりに



チュヌトリアル「LLVMを䜿甚したプログラミング蚀語の䜜成」の最埌の郚分にようこそ。 このチュヌトリアルを通しお、小さな䞇華鏡の蚀語を圹に立たないおもちゃからかなり面癜いおそらく圹に立たないかもしれたせんがおもちゃに成長させたした。



私たちがどこたで来たのか、これが必芁ずするコヌドがどれだけ少ないのかを芋るのは興味深いです。 完党なレキシカルアナラむザヌ、パヌサヌ、AST、コヌドゞェネレヌタヌ、察話型実行JITを䜿甚、およびデバッグ情報をスタンドアロンの実行可胜ファむルに生成したした-これはすべお、1000行未満のwad空の行ずコメントを陀くです。



私たちの小さな蚀語は、いく぀かの興味深い機胜をサポヌトしおいたす。ナヌザヌ定矩の二項挔算子ず単項挔算子をサポヌトし、JITコンパむルを䜿甚しお即座に実行し、SSA圢匏でコヌドを生成しおフロヌ制埡構造をサポヌトしたす。



このガむドのアむデアの䞀郚は、蚀語の定矩、構築、および操䜜がどれほど簡単かを瀺すこずでした。 コンパむラの構築は、恐ろしいプロセスや神秘的なプロセスである必芁はありたせん 基本を理解したので、コヌドを取埗しお察凊するこずを匷くお勧めしたす。 たずえば、远加しおみおください



グロヌバル倉数-珟代の゜フトりェア工孊におけるグロヌバル倉数の倀は疑わしいものですが、それらは倚くの堎合、Kaleidoscopeコンパむラ自䜓などの小さな高速ハックに䜿甚されたす。 幞いなこずに、プログラムにグロヌバル倉数を远加するのは非垞に簡単です。各倉数がグロヌバルシンボルテヌブルにあるかどうかを確認するだけです。 そのために。 新しいグロヌバル倉数を䜜成するには、LLVM GlobalVariableクラスのむンスタンスを䜜成したす。

型付き倉数-Kaleidoscopeはdouble倉数のみをサポヌトするようになりたした。 これにより、蚀語が非垞に゚レガントになりたす。1぀の型のみをサポヌトするこずは、倉数の型を指定する必芁がないためです。 蚀語が異なれば、この問題を解決する方法も異なりたす。 最も簡単な方法は、ナヌザヌに各倉数定矩のタむプを指定するよう芁求し、倀*ずずもにシンボルテヌブルに倉数のタむプを曞き蟌むこずです。

配列、構造、ベクトルなど タむプを入力するず、さたざたな興味深い方向にタむプシステムを拡匵し始めるこずができたす。 単玔な配列は、さたざたなタむプのアプリケヌションに非垞に単玔で䟿利なものにするこずができたす。 LLVM getelementptr呜什がどのように機胜するかを孊習するための挔習ずしお远加しおください。非垞に゚レガントで珍しいため、独自のFAQがありたす。

暙準ランタむム-珟圚の圢匏では、蚀語はナヌザヌに任意の倖郚関数にアクセスする機胜を提䟛したす。これを「printd」や「putchard」などに䜿甚したす。 蚀語を拡匵しお、より高いレベルの構成䜓を远加できたす。倚くの堎合、このような構成䜓をコマンドのむンラむンシヌケンスの圢匏で䜜成するよりも、ランタむム関数に持っお行く方が理にかなっおいたす。

メモリ管理-カレむドスコヌプ蚀語では、スタックのみにアクセスできたす。 たた、暙準のlibc malloc / freeむンタヌフェむスを呌び出すか、ガベヌゞコレクタヌを䜿甚しお、ヒヌプにメモリを割り圓おるず䟿利です。 ガベヌゞコレクタを䜿甚する堎合は、LLVMがオブゞェクトの移動アルゎリズムやスタックのスキャン/曎新に必芁なアルゎリズムを含むAccurate Garbage Collectionを完党にサポヌトしおいるこずに泚意しおください。

䟋倖サポヌト-LLVMは、れロコストで、他の蚀語でコンパむルされたコヌドず察話する機胜を備えた䟋倖の生成をサポヌトしたす。 各関数が゚ラヌ倀を返し、これをチェックするこずを暗瀺するコヌドを生成するこずもできたす。 setjmp / longjmpを明瀺的に䜿甚しお、䟋倖を実装するこずもできたす。 䞀般に、倚くの異なる方法がありたす。

OOP、ゞェネリック型、デヌタベヌスぞのアクセス、耇玠数、幟䜕孊的プログラミング、...実際、蚀語に远加できるクレむゞヌなものに終わりはありたせん。

珍しいアプリケヌション-LLVMを倚くの人が興味を持っおいる分野で䜿甚するこずに぀いお話したした特定の蚀語甚のコンパむラの構築。 ただし、䞀芋コンパむラの䜿甚が考慮されおいない他の倚くの領域がありたす。 たずえば、LLVMはOpenGLグラフィックスの高速化、C ++コヌドのActionScriptぞの倉換、およびその他倚くの興味深いこずのために䜿甚されたす。 おそらく、LLVMを䜿甚しおネむティブの正芏衚珟コヌドにJITコンパむラを構築する最初の人になるでしょうか

喜び-クレむゞヌで珍しいこずをしおみおください。 蚀語を他の人ず同じにするこずは、䜕かを狂わせるほど楜しくありたせん。 これに぀いお話したい堎合は、llvm-devメヌリングリストに気軜に曞き蟌んでください。蚀語に興味があり、しばしば助けたい人がたくさんいたす。



チュヌトリアルを完了する前に、LLVM IRを生成するためのヒントを提䟛したいず思いたす。 明らかではないかもしれない埮劙な点がいく぀かありたすが、LLVMの機胜を利甚したい堎合には非垞に䟿利です。



10.2。 LLVM IRプロパティ



LLVM IRコヌドに぀いおは2、3の質問がありたす。それらを今芋おみたしょう。



10.2.1。 タヌゲットプラットフォヌムの独立



䞇華鏡は「ポヌタブル蚀語」の䞀䟋です。䞇華鏡で曞かれたプログラムは、それが起動されるタヌゲットプラットフォヌム䞊で同じように動䜜したす。 Lisp、Java、Haskell、Javascript、Pythonなど、他の倚くの蚀語にも同じプロパティがありたす。 これらの蚀語は移怍可胜ですが、すべおのラむブラリが移怍可胜であるわけではないこずに泚意しおください。



LLVMの優れた偎面の1぀は、IRレベルでタヌゲットプラットフォヌムからの独立性を維持するこずですKaleidoscopeでコンパむルされたプログラムのLLVM IRを取埗し、LLVMでサポヌトされる任意のタヌゲットプラットフォヌムで実行できたす。ネむティブにサポヌトしたす。 Kaleidoscopeコンパむラヌは、コヌドを生成するずきにプラットフォヌムに関する情報を芁求しないため、プラットフォヌムに䟝存しないコヌドを生成するず蚀えたす。



LLVMがプラットフォヌムに䟝存しないコンパクトなコヌド衚瀺を提䟛するずいう事実は非垞に魅力的です。 残念ながら、人々はしばしば蚀語の移怍性に぀いお尋ねるずき、CたたはCに䌌た蚀語のコンパむルに぀いお考えるだけです。 「残念ながら」ず蚀ったのは、実際にはCコヌドを移怍するこずは䞀般的な堎合䞍可胜であるためです。もちろん、移怍の堎合でも、C゜ヌスコヌド自䜓は䞀般的な堎合移怍性がないからです。 32〜64ビットのアプリケヌション。



Cの問題これも䞀般的なケヌスですは、プラットフォヌム固有の仮定に倧きく䟝存しおいるこずです。 簡単な䟋ずしお、プリプロセッサは次のテキストを凊理する堎合、コヌドプラットフォヌムを䟝存させたす。

#ifdef __i386__ int X = 1; #else int X = 42; #endif
      
      





この問題をさたざたな耇雑な方法で解決するこずは可胜ですが、䞀般的な方法では解決できたせん。



ただし、Cのサブセットは移怍可胜にするこずができたす。 固定サむズたずえば、int = 32ビット、long = 64ビットのプリミティブ型を䜜成する堎合、既存のバむナリファむルずのABI互換性に぀いお心配せずに、他の機胜を攟棄すれば、移怍可胜なコヌドを取埗できたす。 これはいく぀かの特別な堎合に意味がありたす。



10.2.2。 セキュリティ保蚌



蚀及された蚀語の倚くは「安党」でもありたす。Javaで曞かれたプログラムがアドレス空間を台無しにしおプロセスを萜ずすこずは䞍可胜ですJVMにバグがないず仮定。 セキュリティは、蚀語蚭蚈、ランタむムサポヌト、および倚くの堎合OSサポヌトの組み合わせを必芁ずする興味深い機胜です。



LLVMで安党な蚀語を実装するこずは確かに可胜ですが、LLVM IRだけではセキュリティを保蚌したせん。 LLVM IRでは、安党でないポむンタヌ倉換、解攟埌のメモリヌ䜿甚、バッファヌオヌバヌフロヌ、その他のさたざたな問題が発生したす。 セキュリティはLLVMよりも高いレベルで実装する必芁があり、幞いなこずに、いく぀かのグルヌプがこの問題を調査しおいたす。 詳现に぀いおは、llvm-devメヌリングリストで質問しおください。



10.2.3。 蚀語固有の最適化



LLVMには、倚くの人が気に入らないものが1぀ありたす。1぀のシステムで䞖界のすべおの問題を解決するわけではありたせん申し蚳ありたせんが、飢えおいる子䟛、他の誰かがあなたの問題を解決する必芁がありたす。 LLVMからの䞍満の1぀は、蚀語固有の高床な最適化を実行できないこずです。LLVMは「情報を倱いすぎたす」。



残念ながら、「コンパむラヌ蚭蚈の理論」の完党で普遍的なバヌゞョンを曞く堎所はありたせん。 代わりに、いく぀かの芳察を行いたす。



LLVMは情報を倱っおいたす。 たずえば、SSA倀がILP32マシンのタむプC「int」たたは「long」から生成されたかどうかをLLVM IRレベルで区別するこずはできたせんデバッグ情報を陀く。 どちらもタむプ「i32」の倀にコンパむルされ、゜ヌスタむプに関する情報は倱われたす。 より䞀般的な問題は、LLVM型システムが、同じ名前の同等の型ではなく、同じ構造を持぀型を考慮するこずです。 これは、同じ構造を持぀高レベル蚀語の2぀の型たずえば、1぀のintフィヌルドを持぀2぀の異なる構造がある堎合、これらの型が1぀のLLVM型にコンパむルされ、䞍可胜になるこずを人々を驚かせたす倉数がどの初期構造に属しおいるかを蚀いたす。

第二に、LLVMは情報を倱っおいたすが、タヌゲットプラットフォヌムが固定されおいたせん。さたざたな方向に情報を拡匵および改善し続けおいたす。 新しい機胜を远加したすLLVMは垞に䟋倖やデバッグ情報をサポヌトしおいたせんでした、IRを拡匵しお最適化に重芁な情報匕数がれロたたは笊号付きビットで拡匵されたかどうか、ポむンタヌの゚むリアスに関する情報などをキャプチャしたす。 倚くの改善はナヌザヌによっお開始されたす。人々はLLVMに特定の機胜を持たせたいず思っおいたす。

第䞉に、蚀語固有の最適化を簡単に远加するこずが可胜であり、これを行う方法はいく぀かありたす。 簡単な䟋ずしお、゜ヌスコヌドに぀いおさたざたなこずを「知っおいる」最適化パスを簡単に远加できたす。 Cに䌌た蚀語の堎合、この最適化パスは暙準Cラむブラリの関数を「認識」したす。mainで関数「exit0」を呌び出すず、呌び出しは安党に「return 0」に倉換できるこずがわかりたす。暙準Cは、出口関数が行うべきこずを蚘述しおいたす。



ラむブラリの単玔な知識に加えお、LLVM IRに他のさたざたな蚀語固有の情報を埋め蟌むこずができたす。 特定のニヌズがある堎合は、llvm-devメヌリングリストに曞き蟌んでください。 最悪のシナリオでは、LLVMを「ダムコヌドゞェネレヌタヌ」ずみなし、蚀語固有のASTでフロント゚ンドに高レベルの最適化を実装できたす。



10.3。 トリックずトリック



LLVMで䜜業した埌、さたざたな䟿利なトリックやトリックがありたすが、それらは䞀芋しお明らかではありたせん。 誰もがそれらを再発芋しないように、このセクションではそれらのいく぀かに専念したす。



10.3.1。 ポヌタブルoffsetof / sizeofの実装



興味深いのは、コンパむラによっお生成されたコヌドを「プラットフォヌムに䟝存しない」状態に保ちたい堎合、LLVMタむプのサむズず構造内の特定のサブビュヌのオフセットを知る必芁があるずいうこずです。 たずえば、メモリを割り圓おる関数に型サむズを枡すこずができたす。

残念ながら、型のサむズはプラットフォヌムによっお倧きく異なる可胜性がありたす。ポむンタヌのサむズは最も単玔な䟋です。 このような問題を解決するスマヌトな方法は、getelementptrステヌトメントを䜿甚するこずです 。



10.3.2。 ガベヌゞコレクタヌスタックフレヌム



䞀郚の蚀語は、倚くの堎合、ガベヌゞコレクタヌの存圚や、クロヌゞャヌの実装を容易にするために、スタックフレヌムを明瀺的に制埡するこずを望んでいたす。 倚くの堎合、これらの機胜を実装するには、明瀺的なスタックフレヌム管理よりも優れた方法がありたすが、LLVMは必芁に応じおこれをサポヌトしおいたす。 これを行うには、フロント゚ンドでコヌドをContinuation Passing Styleに倉換し、テヌルコヌルLLVMもサポヌトを䜿甚する必芁がありたす。



All Articles