Rust에서 LLVM Intrinsics 호출하기
Posted: November 28, 2015 Filed under: Code, Tokamak Project | Tags: llvm, rust, tokamak Leave a comment요즘에는 내가 보려는 목적으로 기록을 하는 블로깅이 대부분인 듯 하다. Rust는 LLVM으로 구현되어 있고 LLVM 의 Intrinsics를 함수에 매핑해서 호출할 수 있는 기능이 공식적으로 제공된다. 예제는 아래와 같다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(link_llvm_intrinsics)] | |
extern { | |
#[link_name = “llvm.sqrt.f32”] | |
fn sqrt(x: f32) -> f32; | |
} | |
fn main(){ | |
unsafe { sqrt(32.0f32); } | |
} |
LLVM을 이용한 JIT 코드 개발 정리
Posted: November 25, 2015 Filed under: Code, FOSS, Tokamak Project | Tags: JIT, llvm, tokamak Leave a comment현재 작업 중인 Tokamak (가제) 프로젝트서 사용될 LLVM JIT 코드 몇 가지를 작성해보았다. Rust로 작업하고 있기 때문에 llvm-alt 라는 바인딩 라이브러리를 fork해서 작업을 진행했다. fork 한 이유는 버그와 미구현 API 때문인데 maintenance가 기존에 리포트된 버그도 수정 안되길래 아예 fork 해버렸다.
LLVM은 레퍼런스 문서는 참 훌륭하다. 또한 LLVM IR 자체가 프로그래밍 코드와 비슷해서 Java Bytecode를 보다 훨씬 쉬운 듯 하다. 자체는 쉬운 편인데, 친절한 문서는 별로 없다. 만든 녀석들이 워낙 똑똑한 녀석들이라 나 같은 초보들이 뭘 필요하는지는 잘 모르는 모양인데 이 글에 익힌 몇 가지 정리를 한다. 이 문서의 목적은 내가 보기 위해서기 때문에 체계적이지도 않고 부연설명도 없다.
MJIT vs ORC
- MCJIT 전에는 JIT 였음, JIT 는 LLVM 3.5에서 제거됨
- MCJIT는 더 많은 타겟에 대한 네이티브 코드 지원
- MCJIT는 lazy compilation 지원안함, ORC는 지원함. 다시말해 ORC는 함수 실행 전에 code generation을 하기 때문에 일반적으로 code generation time이 짧음
- 의문1: ORC는 thread safe 한가? (관련 링크)
- 의문2: thread safe를 위한 성능 손해는 없는가?
- 많은 새 프로젝트들은 MCJIT보다는 ORC 선택 중 또는 기존 프로젝트들도 전환 중
IR 코드와 Bitcode (BC)
- 프로그래밍 언어는 LLVM 거치면 IR로 변환되고 IR은 다시 BC로 변환되어 최종적으로 native 바이너리 형태로 변환된다. IR과 BC는 어디까지나 LLVM을 위한 intermediate representation 코드임
- IR은 human readable representation 이고 BC는 더 컴팩트한 바이너리 포맷. 로딩은 당연 후자가 빠르므로 런타임 로딩을 위해서는 미리 BC로 빌드를 해놓아야 한다.
- JIT 코드 작성 시에 IR 코드 생성을 해야 할 필요가 있는데 이는 프로그래밍 언어와 JIT 간에 interoperation 을 위해서이다.
- 예를 들면 JIT로 작성한 함수가 인자로 받을 구조체는 프로그래밍 언어에서도 가용해야 하는덷 이런 경우 c++ 등으로LLVM JIT에서 사용할 구조체와 함수등을 구현해 놓고 c++ 코드에서는 해당 구현을 사용하고 LLVM JIT에서는 미리 생성된 IR을 사용한다.
- IR 을 파싱하고 로딩해서 모듈을 생성할 수 있다.
- 생성된 모듈에서 iterator 를 통해 함수 리스트를 얻을 수 있다.
- 이때 함수에 attribute를 부여할 수 있는데 예를 들면 AlwaysInline 같은 것..
- AlwaysInline 속성은 JIT로 작성된 코드 내부에서 호출하는 다른 JIT 함수들은 전부 inlining이 된다. 즉 함수 호출 비용이 줄어든다.
- LLVM JIT를 굳이 어렵게 쓰는 이유는 interpretation cost를 줄이고 복잡한 로직을 주어진 정보를 통해 단순화 시켜 브렌치를 제거하기 위함인데 inlining은 이 목적에 잘 부합한다.
- 다른 속성도 살펴봐야..
- Clang을 통해 emit-llvm 할 경우 extern 으로 감싸야 llvm 으로 함수에 접근 가능하다.
- Clang을 통해 emit-llvm 할 경우 활용되지 않는 구조체는 컴파일러 레벨 최적화에서 제거 되기 때문에 IR에도 표현되지 않는데 이런 경우를 방지하려면 private dummy 함수를 만들어 인자에 struct들을 다 넣어버리면 IR에 struct를 유지시킬 수 있다.
- Clang을 통해 emit-llvm 할 경우 같은 구성을 가진 구조체는 서로 구분하지 못한다. 따라서 다른 구조체의 symbol 이름으로 IR이 출력될 수 있다.
LLVM 링크 정리
Posted: November 11, 2015 Filed under: Code, Tokamak Project | Tags: llvm Leave a commentDocumentation Links
- Kaleidoscope in Rust
- llvm-rs github (forked)
- llvm-rs Documentation
- llvm-sys Documentation
- Rustc LLVM source
- LLVM C API Doxygen
- Instruction Builders in LLVM C API
- IRBuilder.h in LLVM C++
- IRBuilder API in LLVM C++
- LLVM Programmer’s Manual
- Mapping High-Level Constructs to LLVM IR
Presentation Materials
Sample Codes
- https://github.com/imasahiro/llvm-sample
- codegen module of Impala
- Kaleidoscope in C API
- llvm-clang-samples