llvm 版の AcotieScript を動かそうとして挫折した話

http://d.hatena.ne.jp/moriyoshi/20090519/1242704111
このへんのサンプルとかいじってみてたんだけど、llvm3.0だとだいぶコードをいじらないと動かないというか、llvm::getGlobalContext() を渡してやらないといけないように仕様変更されたメソッドとかおおい様子。

わりと acotiescript にかぎらず本家のチュートリアルでもヘッダファイルのパスが変わってうごかなくなってたりして、こまったもの。しばらく互換性をのこすといった配慮もみられないので、3年ぐらい前の llvm 用に作成されたプログラムは、昔の llvm をわざわざいれないとコンパイルできないケースが多発していそう。

なお acotiescript については、以下のように変更したけど動かそうとすると segv した(reinterpret_cast でおちる)。

diff --git a/Makefile b/Makefile
index c3cd47b..cb7e781 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 all:
 	yacc -b parser -dv parser.y
 	lex -o lex.c lex.l
-	g++ $(subst -O2,,$(shell llvm-config --cflags --ldflags --libs)) -o acotiescript parser.tab.c lex.c
+	g++ -g -O0 -o acotiescript parser.tab.c lex.c $(shell llvm-config-3.0 --cppflags --ldflags --libs core jit native) -ldl
 clean:
 	rm parser.tab.[ch] lex.c parser.output acotiescript
diff --git a/parser.y b/parser.y
index d15f5e5..9a5dc97 100644
--- a/parser.y
+++ b/parser.y
@@ -5,6 +5,7 @@
 #include <unistd.h>
 #include <climits>
 #include <dlfcn.h>
+#include <llvm/LLVMContext.h>
 #include <llvm/Module.h>
 #include <llvm/Function.h>
 #include <llvm/PassManager.h>
@@ -12,13 +13,13 @@
 #include <llvm/Constants.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/Support/IRBuilder.h>
-#include <llvm/System/DynamicLibrary.h>
+#include <llvm/Support/DynamicLibrary.h>
 
 struct llvm_acotie_ctx {
     llvm::Module* mod;
     llvm::Function* fun;
     llvm::BasicBlock* block;
-    llvm::IRBuilder* builder;
+    llvm::IRBuilder<>* builder;
     struct {
         llvm::Function* printf;
     } functions;
@@ -88,9 +89,9 @@ print:
         llvm::Function* print_fun = acotie.mod->getFunction("print");
         std::string str($2);
         llvm::GlobalVariable* str_const = new llvm::GlobalVariable(
-                llvm::ArrayType::get(llvm::Type::Int8Ty, str.size() + 1),
+                llvm::ArrayType::get(llvm::Type::getInt8Ty(llvm::getGlobalContext()), str.size() + 1),
                 true, llvm::GlobalVariable::InternalLinkage,
-                llvm::ConstantArray::get(str), "", acotie.mod);
+                llvm::ConstantArray::get(llvm::getGlobalContext(), str), "", acotie.mod);
         acotie.builder->CreateCall(print_fun,
             acotie.builder->CreateStructGEP(str_const, 0));
     }
@@ -171,15 +172,15 @@ void register_builtins()
     static std::string format_str("おうっふー %s");
     llvm::Function* fun = llvm::cast<llvm::Function>(
         acotie.mod->getOrInsertFunction(
-            "print", llvm::Type::VoidTy,
-            llvm::PointerType::get(llvm::Type::Int8Ty, 0), NULL));
-    llvm::BasicBlock* block = llvm::BasicBlock::Create("entry", fun);
-    llvm::IRBuilder* builder = new llvm::IRBuilder(block);
+            "print", llvm::Type::getVoidTy(llvm::getGlobalContext()),
+            llvm::PointerType::get(llvm::Type::getInt8Ty(llvm::getGlobalContext()), 0), NULL));
+    llvm::BasicBlock* block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", fun);
+    llvm::IRBuilder<>* builder = new llvm::IRBuilder<>(block);
 
     llvm::GlobalVariable* str_const = new llvm::GlobalVariable(
-            llvm::ArrayType::get(llvm::Type::Int8Ty, format_str.size() + 1),
+            llvm::ArrayType::get(llvm::Type::getInt8Ty(llvm::getGlobalContext()), format_str.size() + 1),
             true, llvm::GlobalVariable::InternalLinkage,
-            llvm::ConstantArray::get(format_str), "", acotie.mod);
+            llvm::ConstantArray::get(llvm::getGlobalContext(), format_str), "", acotie.mod);
     builder->CreateCall2(acotie.functions.printf,
         builder->CreateStructGEP(str_const, 0),
         fun->arg_begin());
@@ -220,21 +221,21 @@ int main(int argc, char **argv)
         }
     }
 
-    acotie.mod = new llvm::Module("acotie");
+    acotie.mod = new llvm::Module("acotie", llvm::getGlobalContext());
 
     {
-        std::vector<llvm::Type const*> param_types;
-        param_types.push_back(llvm::PointerType::get(llvm::Type::Int8Ty, 0));
+        std::vector<llvm::Type*> param_types;
+        param_types.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(llvm::getGlobalContext()), 0));
         acotie.functions.printf = llvm::Function::Create(
-            llvm::FunctionType::get(llvm::Type::VoidTy, param_types, true),
+            llvm::FunctionType::get(llvm::Type::getVoidTy(llvm::getGlobalContext()), llvm::ArrayRef<llvm::Type*>(param_types), true),
             llvm::Function::ExternalLinkage, "printf", acotie.mod);
         acotie.functions.printf->setCallingConv(llvm::CallingConv::C);
     }
     register_builtins();
 
-    acotie.fun = llvm::cast<llvm::Function>(acotie.mod->getOrInsertFunction("acotie_main", llvm::Type::VoidTy, NULL));
-    acotie.block = llvm::BasicBlock::Create("entry", acotie.fun);
-    acotie.builder = new llvm::IRBuilder(acotie.block);
+    acotie.fun = llvm::cast<llvm::Function>(acotie.mod->getOrInsertFunction("acotie_main", llvm::Type::getVoidTy(llvm::getGlobalContext()), NULL));
+    acotie.block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", acotie.fun);
+    acotie.builder = new llvm::IRBuilder<>(acotie.block);
     if (yyparse()) {
         return 1;
     }

Published: 2012-07-15(Sun) 21:57