간단한 LLVM 실습을 해보겠다.
1. 일단 간단한 C 파일을 작성한다.
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
2. clang으로 hello.c를 컴파일한다.
clang hello.c -o hello
3. clang으로 LLVM bitcode 파일을 하나 생성한다.
clang -O3 -emit-llvm hello.c -c -o hello.bc
여기서-emit-llvm 옵션은 -S와 -c 옵션을 통해 각각 .ll, .bc 파일을 생성한다
참고로 -c 옵션을 주었을 때는 아래처럼 아예 인간이 알아볼 수 없는 형태가 되지만,
-S 옵션을 주면 아래처럼 clang은 인간이 읽을 수 어셈블리를 반환한다. 따라서 엄밀히 말해서는 비트코드가 들어있는 건 아닌듯? (따라서 -S로 만든 .bc는 llvm-dis로 열면 비트코드 포멧이 틀렸다고 나와서 제대로 실행이 안된다.)
4. 만들어진 파일을 돌려보자
1) ./hello로 돌려도 되고,
2) lli hello.bc로 비트코드 포멧을 실행시킬 수 있다. lli는 JIT(just in time) 컴파일러 혹은 인터프리터를 사용하여 이를 실행하게 된다.
5. llvm-dis 기능을 활용해 LLVM 어셈블리를 읽어보자.
llvm-dis < hello.bc | less
아까 clang -O3 -emit-llvm hello.c -S -o hello.bc로 했을 때 결과랑 똑같은듯??
6.이제 hello.bc 파일을 llvm code generator로 컴파일해서 native assembly 파일을 만들어보자.
llc hello.bc -o hello.s
Reference
Getting Started with the LLVM System — LLVM 19.0.0git documentation