Rust + LLVM (inkwell)でHello World
2019-06-09
Tech自作言語の処理系をRustで書いてLLVM IR生成をやろうとしているのですが、とりあえずHello Worldができたのでコードを載せておきます。
準備編は以下です。
Cargo.tomlに以下を追加
[dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" }
llvm-sys = "70"
LLVMの最新版は8ですが、inkwellの対応版がまだないのでLLVM 7を使います。homebrewの場合はbrew install llvm@7
で入ります。
main.rs
use inkwell::context::Context;
use std::error::Error;
fn main() -> Result<(), Box<Error>> {
let context = Context::create();
let module = context.create_module("main");
let builder = context.create_builder();
let i32_type = context.i32_type();
// declare i32 @putchar(i32)
let putchar_type = i32_type.fn_type(&[i32_type.into()], false);
module.add_function("putchar", putchar_type, None);
// define i32 @main() {
let main_type = i32_type.fn_type(&[], false);
let function = module.add_function("main", main_type, None);
let basic_block = context.append_basic_block(&function, "entry");
builder.position_at_end(&basic_block);
// call i32 @putchar(i32 72)
let fun = module.get_function("putchar");
builder.build_call(fun.unwrap(), &[i32_type.const_int(72, false).into()], "putchar");
builder.build_call(fun.unwrap(), &[i32_type.const_int(105, false).into()], "putchar");
// ret i32 0
builder.build_return(Some(&i32_type.const_int(0, false)));
module.print_to_stderr();
Ok(())
}
出力
cargo runするとこんな感じでLLVM IRが出ます。
; ModuleID = 'main'
source_filename = "main"
declare i32 @putchar(i32)
define i32 @main() {
entry:
%putchar = call i32 @putchar(i32 72)
%putchar1 = call i32 @putchar(i32 105)
ret i32 0
}
これをa.llとして保存→lli a.ll
で、画面に「Hi」と出たら成功です。「Hi」は、「Hello, world!」と出すのは文字数が多すぎて面倒なとき用の簡略版Hello Worldです。