TR kizaki Tech Memo

learn LLVM

ref: df4475fecbddd0d91ccc

llvm official

LLVMは一言で言えば、プログラミング言語を作成する為の基盤です。プログラミング言語はコンパイラによってバイナリに変換され実行することができます。それを言い換えれば、自分が考えたプログラミング言語のコンパイラを作ることで自作プログラミング言語を作れます。

そして、コンパイラは通常フロントエンド、ミドルエンド、バックエンドに分けられ、各プロセスで様々な処理をしています。特にミドルエンド、バックエンドでは中間言語や各アーキテクチャに対するたくさんの最適化を施さなければなりません。この最適化を預けてフロントエンドだけを考えればコンパイラが作れるというものがLLVMです。LLVMは強力な型システムや厳密な制約を持っていて、これにより高度な最適化技術は実現します。更にLLVMはJITを作る事ができます。JITは通常実装するのが大変ですが、LLVMを使えば楽に実装できます。更に更に他の言語でコンパイルされたLLVMの言語とリンクする事ができます。だから自分で作った言語でC言語の関数を使うことができます

┌─(~/dev/emcc_test/test)────────┐
└─(19:42:46 on main ✖ ✹ ✭)──>  clang -S -emit-llvm -O3 uhouho.c 
┌─(~/dev/emcc_test/test)────────┐
└─(19:43:17 on main ✖ ✹ ✭)──> ls                                ──(Sun,May14)─┘
uhouho.c  uhouho.ll
┌─(~/dev/emcc_test/test)────────┐
└─(19:43:22 on main ✖ ✹ ✭)──> llc uhouho.ll                     ──(Sun,May
┌─(~/dev/emcc_test/test)────────┐
└─(19:45:34 on main ✖ ✹ ✭)──> ls                                ──(Sun,May14)─┘
uhouho.c  uhouho.ll uhouho.s
┌─(~/dev/emcc_test/test)────────┐
└─(19:45:42 on main ✖ ✹ ✭)──> clang uhouho.s -o uhouho          ──(Sun,May14)─┘
┌─(~/dev/emcc_test/test)────────┐
└─(19:46:29 on main ✖ ✹ ✭)──> ls                                ──(Sun,May14)─┘
uhouho    uhouho.c  uhouho.ll uhouho.s
┌─(~/dev/emcc_test/test)────────┐
└─(19:46:36 on main ✖ ✹ ✭)──> ./uhouho                          ──(Sun,May14)─┘
uhouho!
  • the LLVM intermediate representation ("LLVM IR")
; ModuleID = 'uhouho.c'
source_filename = "uhouho.c"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx12.0.0"

@str = private unnamed_addr constant [8 x i8] c"uhouho!\00", align 1

; Function Attrs: nofree nounwind ssp uwtable
define i32 @main() local_unnamed_addr #0 {
  %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([8 x i8], [8 x i8]* @str, i64 0, i64 0))
  ret i32 0
}

; Function Attrs: nofree nounwind
declare noundef i32 @puts(i8* nocapture noundef readonly) local_unnamed_addr #1

attributes #0 = { nofree nounwind ssp uwtable "darwin-stkchk-strong-link" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "probe-stack"="___chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
attributes #1 = { nofree nounwind }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 1]}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 7, !"PIC Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Apple clang version 14.0.0 (clang-1400.0.29.202)"}