Creating My Own Smart Contract Languages Using LLVMしたい
EVMターゲットの自作言語を書いてみたいと思ってこのページを読んだ。(経緯はここ)
Creating Your Own Smart Contract Languages Using LLVM | by Alan Li | Medium
結論を言えばこれを読んだだけではEVMで動くものは書けなかった(自分の力では)。
この記事は、「Kaleidoscope」というLLVMのチュートリアルで作る言語をベースにしてEVMで動くように手を加えていくという趣旨で、EVMで動かすためには追加でどういうことをしないといけないかが解説されている。
ただ、すべての追加・修正コードを載せるまではしていなくて、キーになるコードのみが載っているという感じだった。 一応記事の最後に complete source code list というGitHub Gistへのリンクがあるんだけど404になっていて見ることができない。 記事を読みながら暗中模索であれこれコードをいじってみても、EVM,LLVM,C++すべての知識が圧倒的に足りない状態ではうまく動作するコードが書けなかった…。
とはいえEVMで動作するコードに最低限必要なものは大まかにわかったような気がする。たとえば浮動小数点数が扱えないよとか、function dispatcher(main関数)というものが必要だとか、EVMからの値の受け取り方だとかもなんとなく掴めて、少し前に進んだ気はする。 それとLLVM IR -> EVMアセンブリ -> EVMバイナリ -> EVMバイトコードまで変換する方法と、そのバイトコード(スマートコントラクト)をEVMで動かす方法もわかった。これは大きな収穫だー。
LLVM,C++よくわからんとはいえ、結局こういう入力をした時に
def foo(a b) a*b + 2 * a + 3 * b;
こういうLLVM IRを返せばいいことがわかったので、単純なものならなんとかなる気がする。
define void @main() {
entry:
call void @llvm.evm.mstore(i256 64, i256 128)
%0 = call i256 @llvm.evm.calldataload(i256 0)
%1 = call i256 @llvm.evm.calldataload(i256 32)
%2 = call i256 @foo(i256 %0, i256 %1)
call void @llvm.evm.mstore(i256 0, i256 %2)
call void @llvm.evm.return(i256 0, i256 32)
unreachable
}
define i256 @foo(i256 %a, i256 %b) {
entry:
%multmp = mul i256 %a, %b
%multmp1 = mul i256 2, %a
%addtmp = add i256 %multmp, %multmp1
%multmp2 = mul i256 3, %b
%addtmp3 = add i256 %addtmp, %multmp2
ret i256 %addtmp3
}
; Function Attrs: nounwind writeonly
declare void @llvm.evm.mstore(i256, i256) #0
; Function Attrs: nounwind readnone
declare i256 @llvm.evm.calldataload(i256) #1
; Function Attrs: noreturn nounwind
declare void @llvm.evm.return(i256, i256) #2
attributes #0 = { nounwind writeonly }
attributes #1 = { nounwind readnone }
attributes #2 = { noreturn nounwind }
KaleidoscopeのチュートリアルもChapter3まではそんなにボリュームなさそうだしやってみようかなあ。