* 短期的な開発方針
-(by [[K]], 2018.04.04)

** 言語の基本構成
-一般的なC言語は、C言語のソースコードを読み込みんで、アセンブラのソースコードを出力する。そしてアセンブラがアセンブラのソースからオブジェクトファイルを出力し、リンカはオブジェクトファイルから実行ファイルを生成する。
-この多段構成は、正解だと私も思う。・・・だからEssenもできるだけ多段にする。
-多段の何がいいのかというと、開発中の言語が気に入らなくなったときに、全部を作り直さなくてよくなるということである。上層レイヤは捨てることになるだろうが、下層のいくつかのレイヤはそのまま使えるので、手間を減らすことができる(はずだ)。
-今までのEssenの開発の何が一番非効率だったのかといえば、ようするに何度も何度も作り直しをしてきたことだから。そのたびにノウハウはたまっていて、こちらの技術力は上がっているのだけど、しかしだからといって最初からの作り直しはやはり時間がかかる。だから作り直しをしなくても済む構造を目指さなければいけない。それには多段が一番だ。
-C言語では、C言語の次はアセンブラであり、そこには1階層しかないが、Essenではここを何回層にも分けようと思う。・・・いや、たいていのC言語は内部で中間表記をたくさん持っていて、だから本当は内部も多層になっているのだろう。だからそういう意味ではEssenはそれと似た構造を目指していると言ってもよい。Essenが優れていると言いたいわけではない。

~
-今考えているのは以下のような構成である。
--Essenのソースコード
--(ここをさらに何段か分割したいが、未設計)
--#4 機種依存のないアセンブラ(レジスタはなく、メモリに対して自由に演算できる)
--#3 機種依存のあるアセンブラだが、最適化されていなくて無駄がある
--#2 機種依存のあるアセンブラで、最適化されていてもう無駄はない
--#1 バイナリをメモリ内で実行する仕組み(JITコンパイルして実行するために必要な仕組み)
-#1のレイヤについては[[memo0001]]のJITBでほぼできているので問題ない。
-#2のレイヤについては要するにただのアセンブラを作ればいいだけなので、特に難しいことはない。しかもこのアセンブラは主にバックエンド用なので、記法を多少改変してもいいと思っている。たとえばWORDとかDWORDとかという表記は本質的ではないと私は思う。M10.とかM20.でいいではないか、ええとM10というのは memory 0x10 bits という意味である(つまりWORD)。レジスタもEAXなどと書くのではなく、R20.EAXと書けばいいと思っている。gasのようにパーセントを使わせるのは私の好みではない。
-#3→#2の処理について主に何を最適化するかだけど、まずはジャンプ命令を改善する。高級言語で雑にコードを生成すると、別のジャンプ命令へジャンプする、みたいなことがよく起きる。それはもちろん実行時間の無駄なので、最終的にどこに行くかを追いかけて、そこへ直接行かせるようにする。一度も実行されないコードも除去する。・・・次にメモリに「テンポラリ属性」を付ける。テンポラリ属性メモリは、他の関数によって書き換えられたり、ポインタアクセスによって変更されたり参照されたりはしないようなメモリのことである。これはC言語で言うところの「register属性」とほぼ同義だ。今のC言語の多くはどの変数が一時変数なのかを自動で判断しているが(そしてたまに誤判定もするけど)、とりあえず#3→#2の変換をする際には自動判定はしない。明示的に属性を付ける。そうすれば最適化は難しくない。
 // Txxは、Mxxにテンポラリ属性を付けたもの.
 MOV R20.EAX,T20 [R20.EBP+20]
 ... (この間、ラベル宣言文はないとする)
 MOV R20.EAX,T20 [R20.EBP+20] // もしここまでの流れでEAXを変更していなければ、このMOV命令は除去できる
 
 MOV T20.[R20.EBP+20],R20.EDX
 ... (この間、ラベル宣言文はないとする) 
 MOV T20.[R20.EBP+20],R20.ECX // ここまでの流れで誰も[R20.EBP+20]にアクセスしていないのなら、上のMOV命令は不要なので除去できる
 // またこの先においても、もしT20.[R20.EBP+20]へのリードアクセスがあれば、それはR20.ECXで代用できる、もしECXを変更していなければ。
-基本的に、この程度の最適化で十分だと思っている。それ以上を目指すと複雑になるし、最適化処理にも時間がかかる。JITコンパイラにおいては、コンパイル時間も重要なので、むやみに丁寧な最適化をすればいいというものではない。
-そしてさらにいえば、今年はここまでの最適化すらやらないかもしれない。それよりもさっさと上位レイヤを作ってしまう方がいいかもしれないから。キャンプやSecHack365の学生たちは、上位レイヤを使ってプログラムを書きたいだろうから。
-#4のレイヤは、上位レイヤが実CPUの構成に悩まされないようにするためのものである。レジスタは全部で何本あるのかとか、レジスタ幅は32ビットなのか16ビットなのか64ビットなのかとか、レジスタの直行性はどうなのかとか、そんなことを気にしなくてよくするためのものである。基本的にレジスタはなく、メモリ・メモリ間で演算する。もちろんx86にそんな命令はないので、#3では実レジスタを使ったコードに変換されることになる。このレイヤは最適化を気にする必要はないので、上手にレジスタを割り当てる以外には気にすることはない。

** 短期的なスケジュール
-自分の開発スキルを信じれば、#4→#3のコンパイラ、#3→#2のコンパイラ(といってもひとまずほとんど素通り)、#2→#1のアセンブラは、4月いっぱいでひとまずできると思う。そこから1ヶ月かければ、連休を加味しても、おそらくある程度の高級言語が動くようになっているのではないかと思う。これならセキュリティキャンプにもSecHack365にも間に合うはずだ。

** どうして既存のライブラリを活用しないのか?
-それなりの規模の言語を作ろうという場合は、普通、何らかのライブラリや、既存の実装を利用する。たとえばGCCのコアを利用するとかLLVMのコアを利用するとか、そういったことである。
-そうすれば効率よくよいものができるということは私にもわかっている。しかし一方で、私は今までそういう状況下にあってもあえて全部自分で作るという道を選択していて、そのたびにかなり良いものができているので、今回もあえて既存のものを活用することはしないで全部作ってみたいと思っている。
--うまく行った例: OSのOSASK、アセンブラのnask、JavaみたいなVMを作ってみたOSECPU-VMなど
--うまく行った例: OSのOSASK、アセンブラのnask、JavaみたいなバイトコードVMを作ってみたOSECPU-VMなど



* こめんと欄
#comment



トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS