ライトにはじめる LLVM Python は 64bit 環境だと int 、 float は 64bit となっているので、気をつけてください。 Chapt er2 i32 f32 ir. IntType(32) ir. FIoatType() def get_ir_type(v) : 型推論が終わったら LLVM IR を生成していきます。こでは LLVMCodeGenerator を定義 ロ LLVM IR へ変換 return self. generic visit(node) node. type get_ir_type(node. n) def visit_Num(se1f, node) : class TypeInferencer(ast. N0deVisitor) : AST を visit していき、変数が現れた場合に、その node に type を付与していきます。 上記のように python のデータ型から LLVM IR のデータ型に変換する関数を準備します。 else: return raise Exception("ERROR, unknown type") print("type: return i32 int: elif t return f32 float: if t # float なら f32 、 int なら i32 しました。 class LLVMCodeGenerator(ast. NodeVisitor) : init_(self, ret_type) : def # 省略 def generic visit(self, node): return ast. NodeTransformer. generic visit(self, node) この LLVMCodeGenerator の動作はすごくシンプルです。純粋に AST を辿っていき、構文 に対して対応する LLVM のコードを IRBuiIder で作っていくだけです。ただし、実装はシン 44
ZBrush クリエイターになろう ! Chapter 1 左右対称にポーンを設定する場合は、画面左のオプションタブから X 軸ミラーにチェックを 人れ、 Shitf + E でポーンを追加します。 ( 腰に root となるポーンを配置し、それに子ポーンを 連結していきます ) 。下記 URL を参照し、名前と親子関係を設定してください。 https: 〃 howto.clip-studio.com/library/page/view/clipstudiocoordinate 003 001 ー 003 △全身にポーンを配置し、ポーン名称を変更。 Ctrl + P を押して骨格と肉を結合させよう。 マネキンに合わせてポーンを人れていく作業なので、基本的に難しいところはあまりありま せん。関節運動の軸となる場所にポーンのポールが来るように配置していきましよう。 ポーンの配置が終わったら、まずオプジェクトモードでマネキンを右クリックし、次に Shift を押しながらアーマチュアを右クリックします。そして Ctrl + P を押してアーマチュア変形 > 自動のウェイトでを選択します。これによって . obj とアーマチュアの間に従属関係が設定さ れ、ポーンの移動に従ってポリゴンが変形するようになります。 ( ※なお、読み込んだ . 。 bj ファイルが Non-Manifold な状態の場合、自動ウェイト設定が失敗 します。 Mesh 3D Print ToolBox などのアドオンで Non-Manifold を解消してください ) 。 モードを「ポーズモード」に切り替えて手足を動かし、特に破綻なく形状が変化すればポー ン設定完了です ! ファイル > 工クスポート >FBX(. fbx) で書き出しましよう ! 23
Chapter 3 接続確認 プログラムでドローンを飛ばそう ! ではいよいよプログラムからドローンに接続します。ここが問題なくできればもう飛んだも同然です。 コマンドプロンプトで N 。 de. js のモジュールをインストールしたフォルダに移動して connect. js を 実行しましよう。 ( もちろんドローンのスイッチ ON にするのを忘れずに ! ) >C:\>cd C:\apps\drone\ >C:\apps\drone-»node connect. js さて上手く接続・・・できない ! 「 LIBUSB-ERROR_NOT_SUPPORTED 」って出てる。サポートしてないってな んだ ? さっき OS からペアリング接続出来たじゃないか ! はいそうなんです。どうやら windows 上での noble での BIueto 。 th 接続では通常のドライバをサポー トしておらず WinUSB ドライバにする必要があるようです。これだけ聞いても何のことやらだと思い ますが、「 zadig 」というアプリケーションを使うことでこのドライバを変更出来ます。 Google 先生 に聞いて最新版をダウンロードしましよう。ダウンロード後はインストール不要で exe をそのまま実 行します。実行後は BIuetooth のデバイスを選択して変換後のドライバに WinUSB を選択します。 日 Zadig Device Options Help C5R8510 A10 5 devices found. WCID こ IJSB ID 0A12 0001 ロ X RepIace Drive 「 図 6. zadig でのドライバ変換 ロ Edlt ト 10 肥 lnformation WinUSB flibusb) libusb-win32 libusbK WinLlSB ( Microso 代 ) Zädig 2.2.5S9 これで準備は本当に終わりです。再度コマンドを実行します。 >C:\>cd C:\apps\drone\ >C:\apps\drone>node connect. js > e014ac8e3dc3 Mars_241915 > 1 : Ma 「 s ー 241915 (e014ac8e3dc3), RSSl-13 おお ! ! ドローンの ID が表示されましたね。 ム実行へ進みましよう ) こまでくればもう飛んだも同然です。次のプログラ 62
llvmlite ではじめる JIT コンパイラ IChapter 2 さて、やっていることは非常にシンプルです。 LLVM IR を作成するためには 1RBui1der を使います。これに実行したい命令の順番通りに、 API を使ってどんどん定義していきます。 最終的に LL Ⅷ IR として問題がないかチェックを実施しています。 ロ Pass を使った最適化 LLVM には Pass という最適化を実施する仕組みがあります。 pass は LLVM IR に対して作 用する機能で、 LL Ⅷ IR の変換を行います。下図がイメージなのですが、例えば無駄なスト ア処理などを排除したいなどの最適化を実施する場合は、 pass を使って LLVM IR の変換を 行います。 図 3 LLVM IR を Pass で変換するイメー シ ' LLVM IR ( 変換前 ) Pass LLVM ( 変換後 ) 下図は llvmlite で Pass を定義して、 LLVM IR を最適化して出力するコードです。 # pass を定義して最適化した LL Ⅷ工 R を生成 llvm. create_pass_manager_builder() pmb pmb. opt_level 1 pm = llvm. create module_pass_manager() pmb. populate(pm) pm. run(llvm_ir_parsed) 39 して a を 2 倍にしてから加算処理をしているなど、細かい最適化が入っています。 っていることがわかると思います。特に a を 2 回加算している処理を、 a を lbit 左シフト また、 Pass を通した後の LLVM IR は以下のようになります。非常にシンプルなコードにな
llvmlite ではじめる JIT コンパイラ lChapter 2 ても万能なものではなく、かなり挙動が制限されたコンパイラをつくることが目標です。 本記事は以下の流れで解説します。 llvmlite 簡単なコンパイラを作ってみよう llvmlite の紹介 LLVM IR の読み方 LLVM の概要 ロ LLVM の概要 了承いただければと思います。 把な表現をしている記載があります。わかりやすさに焦点を置いているので、 諸注意ですが、本記事ではコンパイラ技術をざっくりと解説しているため、非常に大雑 その点はご 的な印象を持ちますが、要はプログラミング言語を機械語に変換するための中間言語と思 パイラ用語です。 LLVM にも LLVM IR という中間表現が定義されています。 " 表現 " だと抽象 まず LLVM IR についてです。 IR とは中間表現 (lntermediate Representation) というコン ■ LLVM IR ンドの関係図を記載します。この図を元に 3 人の登場人物について解説をします。 を機械語へ変換するためのバックエンドです。以下に LLVMIR 、フロントエンド、バックエ という中間表現、プログラミング言語を LL Ⅷ IR へ変換するためのフロントエンド、 LL Ⅷ IR LLVM を理解するためには、 3 つの登場人物をおさえれば OK です。その 3 人とは、 LLVMIR ロ LLVM の全体像 んなプロセッサ上で実行してあげるよ ! 」というツールです。 LLVM とは、「どんなプログラミング言語でも、 LLVMIR という中間表現に変換すればいろ しいところもあります。ただ、この章でお伝えしたいことは以下の 1 行だけです。 本章では LLVM の概要について説明します。しつかり解説したいので、ちょっと長ったら
llvmlite ではじめる JIT コンパイラ lChapter 2 変換する機能を開発しないといけません。これは非常にたいへんなことです。しかし、 LLVM は LLVM IR に変換することで、バックエンドがそれぞれのプロセッサに合わせた機械語を 出力します。バックエンドのおかげで、プログラミング言語を開発するという敷居は非常 に下げられたのです。 実のところ、筆者はこのバックエンドに関してはド素人です。筆者の推薦図書である「き つねさんでもわかる LLVM ( 出版 : インプレスジャパン ) 」にもバックエンドについてはほとん ど記載がありません。もしバックエンドについて詳細を知りたい方がいらっしやれば、 自身で情報を集めていただきますようお願いいたします。 ■ Java と似ているかも LLVM は Low LeveI VirtuaI Machine の略で、つまりⅧなのです。ちょっと Java に例え て説明をしてみます。 Java は「 30 億デバイス上で動作する」という触れ込みですよね。 JVM という仮想マシン があり、 Java プログラミング言語で書かれたアプリケーションはバイトコードに変換され、 バイトコードは仮想マシン上で動作をします。先ほどバックエンドの説明で述べた通り、 様々なプラットフォームの差異を仮想マシンが吸収してくれます。そのためアプリケーシ ョン開発者は Java でアプリケーションをつくることのみに集中して開発することができま す。これは非常に素晴らしい仕組みで、 scala や Groovy はそれを利用しています。図示す ると以下のような感じでしようか ? この Java のやっていることは LLVM とほぼ同じです。 LLVM IR に変換することでプラットフォームを意識することがないのです。 ・図 2 J Ⅷでプログラムを実行する流れ Java G 「 oovy ScaIa → Bytecode → JVM JVM JVM → → →・ ARM X86 Power 33
Chapter2 っていただいて大丈夫です。 ライトにはじめる LLVM また、 LLVM では前章で説明した最適化を LLVM IR に対して行います。 ・図 1 LL Ⅷでプログラムを実行する流れ ても後の章で実際に解説します。 Frontend Optimize LLVM IR Backend Rust Swift ■フロントエンド この最適化につい ARM X86 Power 次に、フロントエンドについて説明します。この図ではプログラミング言語の例として C や Haskell が登場していますが、別にプログラミング言語はなんでも OK です。フロント工 ンドは任意のプログラミング言語を LL Ⅷ IR に変換する部分のことを指します。 LLVM では LL Ⅷ IR に変換するためのライフ。ラリを提供しています。本記事では後章でこのフロントェ ンドについて解説します。 ■ノヾックエンド 最後にバックエンドについてです。バックエンドは LLVM IR をいよいよプロセッサ上で 動作する機械語に変換する部分です。 LLVM でコンパイラを開発する恩恵は主に ーにある と筆者は思っています。と言いますのも、プロセッサにはいろいろな種類があります。例 えば、 Intel(x86) 、 ARM 、 IBM(Power) などです。これらのプロセッサ上で動作する機械語は それぞれのプロセッサごとに仕様があります。もし、あなたがオレオレ言語を開発してそ れを様々なプラットフォームで動作させたい場合、それぞれのプロセッサ仕様の機械語に 32
Chapter2 2 , 3 ) Python の関数を定義する 関数を AST ( 抽象構文木 ) に変換する AST から LLVM IR へ変換を実施する 引数の値を渡して実行する Pass で LLVM IR を最適化する ライトにはじめる LLVM ちなみに Python コードのイメージはこんな感じです。 def add(), b, ( ) : return a 十 b 十 ( compiler. exe(add, r et print(ret) ロ AST をつくる 1 , AST を作成するのは非常に簡単で、 Python の標準ライプラリを使えば OK です。以下、サ return X 十 y def func(), y) : xmport inspect xmport ast ンプルです。 class ASTTraverser(ast . NodeVisitor) : def generic_visit(self, node) : print("{}:{}". format(type(node) ・ name ast. NodeVisitor. generic visit(self, node) node. dict 実行結果は以下の通りです。ちょっと見にくいですね、 42 ごめんなさい。
Chapter 1 ZBrush クリエイターになろう ! ODynaMesh でトボロジー修正だ ! ( ちょうど画像を拡大したときにジャギーが目立つのと同じ仕組みですね ) これはメッシュを膨らませたために密度が下がり、トボロジーが狂ってしまったためです。 そうこうしているうちに、粘土を盛り上げた部分がカクカクし始めるのに気が付くでしよう。 12 指定が終わったら、 DynaMesh をクリックしてください ! は 128 ですが、今回のモデルなら 512 や 1024 程度にしておくとよいでしよう。 ResoIution の Geometry>DynaMesh から Resolution( 再配置するメッシュの解像度 ) を指定します。初期値 シュを再配置して、できるだけ均等な正方形メッシュへと変換してくれます。 そこで今度は DynaMesh を使ってみましよう。 DynaMesh は現在の Tool の形状を元にメッ 大きくなって、 ZBrush の挙動が重くなってしまいます。 しかし先程のように Devide でメッシュを分割するのは悪手です。 T 。 ol 全体のポリゴン数が △ LLVM ドラゴンの頭部を盛り上げようとして、正方形だったポリゴンが崩れてしまった。
「伺か」を JavaScript で車輪の再発明 Chapter 4 一声をつける デスクトッブマスコットを見てると、ニコニコ動画のゲーム実況を思い出しませんか ? せつかくなのでニコニコ動画のゲーム実況みたいに、マスコットキャラクターに ( 音声で ) しゃべら せてみましよう。 JavaScript でテキストの読み上げ機能実装も実は思った以上に簡単で、プラウザの標準機能として 用意されていたりします。テキストの読み上げだけなら以下の一行で OK 。 speechSynthesis. speak(new SpeechSynthesisUtterance(" こんにちは ")) ; 声の大きさや早さ、高さも設定ができます。特に声の高さを変更すると別の人が話しているような演 出ができるので、会話劇を表現するのに向いているなと思います。 new Speec11SYIIL11esisUtLerance() ; SYIlChes synthes. volume = 1 ; / / 声の大きさ = 1 ; 〃声の早さ synthes. rate = 2 ; 〃声の高さ synthes. pitch synthes. text こんにちは ' "ja—JP" synthes. lang speechSynthesis. speak(synthes) ; こういった新しいプラウザの標準機能って、 InternetExplorer が対応してないとかで web アプリに 入れにくかったりするのですが、 Electron だとプラウザ互換性をあまり気にしなくていいので、か なり助かります。