글을 작성하기에 앞서 한양대 Computer Architecture and System Software LAB에서 제공받은 자료를 바탕으로 작성되었다.
이번 글에서는 clang, llvm-as, llvm-dis, llc의 명령어를 사용해 IR 코드 (.bc, .ll 파일)와 바이너리(실행 파일)로 컴파일하는 방법을 알아보도록 하겠다.
clang은 LLVM IR 기반 컴파일러 중 하나로, C, C++등 다양한 언어들을 IR 단계로 컴파일 하도록 지원한다.
컴파일러는 프론트엔드와 백엔드로 나뉘어지는데 clang은 언어에 따라 컴파일 해주는 프론트엔드 부분을 담당하고 있다.
다음을 보면 .c와 .cpp 소스코드는 clang을 통해 llvm bitcode로 컴파일되는것을 알 수 있다.
llvm-as, llvm-dis는 IR 레벨의 Assembler와 Disassembler로, 이를 사용하여 서로 human-readable assembly 형태의 코드(.ll 파일)와 bitcode 형태의 코드(.bc)로 바꿀 수 있다.
llc는 LLVM 백엔드 컴파일 명령어로, bitcode 형태를 머신 어셈블리로 변환한다.
Clang의 사용법
GCC에서 사용하는 컴파일 옵션을 대부분 지원하며 다음과 같이 사용한다.
$ clang <source_file> [-o output_path]
Clang을 사용하여 HelloWorld.c 파일을 컴파일하고 실행한다.
다음은 IR레벨 까지 compile 해주는 명령어이며 각각의 명령어는 .bc와 .ll파일로 만들어진다.
$ clang –emit-llvm -c <source_file> [-o output_path] # 소스파일을 bitcode 형태로 바꿔주는 명령
$ clang –emit-llvm -S <source_file> [-o output_path] # 소스파일을 Human readable assembly(*.ll)로 바꿔주는 명령
• clang을 사용하면 IR에서 실행가능한 바이너리로 컴파일 할 수 있습니다.
(llc로 IR코드를 어셈블리로 컴파일하고 어셈블리를 돌린 후 링킹해서 실행가능한 바이너리를 얻을 수도 있습니다.)
LLVM Assembler, Disassembler와 LLC
- llvm-as(assembler), llvm-dis(disassembler)를 사용하여 LLVM IR의 형태를 변환 할 수 있다.
$ llvm-as <IR file> [-o=output path] # readable (*.ll) 에서 bitcode (*.bc)로 변환
$ llvm-dis <IR file> [-o=output path] # bitcode(*.bc) 에서 readable (*.ll)로 변환
- llc를 사용하면 IR을 타겟 머신의 바이너리 (어셈블리)로 컴파일 할 수 있습니다.
$ llc <IR file> [-o output_path]
다음은 컴파일 한 assembly 파일(.s ) 입니다.
Human Readable Assembly 파일을 읽어오기
다음의 컴파일 옵션을 사용해 컴파일하고 .ll(Human Readable Assembly) 파일을 읽도록 하겠다.
$ clang++ <file> $(llvm-config --cxxflags --ldflags --system-libs --libs [name list])
ReadIR.cpp 파일은 llvm::Module을 통해 .ll파일을 읽어온다.
여기서 llvm::Module 클래스는 컴파일 및 최적화를 수행하기 위한 단위를 나타내는 클래스로 보통 하나의 파일을 의미한다.
IR파일을 parsing할 때 필요한 llvm::LLVMContext 클래스는 전체 컴파일과정에서 일관된 자료형 및 전역 변수 등을 포함하는 컨택스트를 나타낸다.
추가적인 참고사항
LLVM이란?
https://zeddios.tistory.com/1175
'컴파일러' 카테고리의 다른 글
[디지털논리] FPGA란? (0) | 2021.08.27 |
---|---|
[컴파일러] 5. LLVM을 이용해 Instruction 위치 이동(feat 메모리 명령어 종속성) (2) | 2021.08.02 |
[컴파일러/LLVM] 2. Module, Function, Basic Block 순회하며 Instruction 출력하기 (0) | 2021.08.01 |
[컴파일러] 4. LLVM을 이용한 IR 레벨에서 명령어 삭제 및 생성 (0) | 2021.07.28 |
[컴파일러] 3. LLVM을 이용하여 프로그램 안의 특정 명령어 세기 (0) | 2021.07.22 |