Wednesday, June 4, 2008

I've spent the last month of my daily bus rides exploring LLVM. It's a really great framework, and now I've gone past the toy languages in the tutorials to work on wrapping the API in Ruby. I spent some time trying to wrap the C++ API using Rice and/or rb++, the latter is not quite complete enough yet, and the former reminds me of why I enjoy Ruby so much over my days of hacking in C++, namely the horror of template error reporting in most C++ compilers:


g++ -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 -I. `llvm-config --cxxflags core` -I/usr/local/include -fno-common -arch i386 -Os -pipe -fno-common -Wall -g -c llvm.cpp
/usr/local/include/rice/detail/../detail/to_ruby.ipp: In static member function ‘static Rice::Object Rice::detail::to_ruby_::convert(const T&) [with T = llvm::Constant*]’:
/usr/local/include/rice/to_from_ruby_defn.hpp:67: instantiated from ‘Rice::Object to_ruby(const T&) [with T = llvm::Constant*]’
/usr/local/include/rice/detail/../detail/Auto_Member_Function_Wrapper.ipp:1188: instantiated from ‘static VALUE Rice::detail::Auto_Member_Function_Wrapper::call(VALUE, VALUE, VALUE) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&, const llvm::FunctionType*), Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&, Arg2_T = const llvm::FunctionType*]’
/usr/local/include/rice/detail/../detail/Auto_Member_Function_Wrapper.ipp:1171: instantiated from ‘Rice::detail::Auto_Member_Function_Wrapper::Auto_Member_Function_Wrapper(Func_T, const Rice::detail::Exception_Handler*) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&, const llvm::FunctionType*), Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&, Arg2_T = const llvm::FunctionType*]’
/usr/local/include/rice/detail/../detail/wrap_function.ipp:89: instantiated from ‘Rice::detail::Wrapped_Function* Rice::detail::wrap_function(Ret_T (Self_T::*)(Arg1_T, Arg2_T), const Rice::detail::Exception_Handler*) [with Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&, Arg2_T = const llvm::FunctionType*]’
/usr/local/include/rice/detail/../detail/define_method_and_auto_wrap.ipp:16: instantiated from ‘void Rice::detail::define_method_and_auto_wrap(VALUE, const char*, Fun_T, const Rice::detail::Exception_Handler*) [with Fun_T = llvm::Constant* (llvm::Module::*)(const std::string&, const llvm::FunctionType*)]’
/usr/local/include/rice/detail/../Module_impl.ipp:66: instantiated from ‘Derived_T& Rice::Module_impl::define_method(const char*, Func_T) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&, const llvm::FunctionType*), Base_T = Rice::Data_Type_Base, Derived_T = Rice::Data_Type]’
llvm.cpp:51: instantiated from here
/usr/local/include/rice/detail/../detail/to_ruby.ipp:7: error: creating array with size zero (‘no_to_ruby_conversion_defined’)
make: *** [llvm.o] Error 1

Clear as mud, no? 

I also gave swig a try, but it choked on the C++ headers. I'll probably give it a try using the C API, or just create some Ruby to parse the c headers and generate an interface.



No comments: