[macruby-changes] [1578] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Tue May 19 22:53:09 PDT 2009
Revision: 1578
http://trac.macosforge.org/projects/ruby/changeset/1578
Author: lsansonetti at apple.com
Date: 2009-05-19 22:53:09 -0700 (Tue, 19 May 2009)
Log Message:
-----------
working on an experimental AOT compiler
Modified Paths:
--------------
MacRuby/branches/experimental/TODO
MacRuby/branches/experimental/include/ruby/ruby.h
MacRuby/branches/experimental/main.cpp
MacRuby/branches/experimental/rakelib/builder.rb
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/roxor.h
MacRuby/branches/experimental/ruby.c
Modified: MacRuby/branches/experimental/TODO
===================================================================
--- MacRuby/branches/experimental/TODO 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/TODO 2009-05-20 05:53:09 UTC (rev 1578)
@@ -61,7 +61,7 @@
[/] reimplement all IOs using CFStreams
[X] clean string.c (remove previous bytestring stuff)
[/] implement eval/binding (irb)
-[ ] implement the BridgeSupport plumbing
+[X] implement the BridgeSupport plumbing
[ ] implement threading
[ ] Thread
[ ] light threading
Modified: MacRuby/branches/experimental/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/ruby.h 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/include/ruby/ruby.h 2009-05-20 05:53:09 UTC (rev 1578)
@@ -934,7 +934,7 @@
VALUE rb_equal(VALUE,VALUE);
-RUBY_EXTERN VALUE ruby_verbose, ruby_debug;
+RUBY_EXTERN VALUE ruby_verbose, ruby_debug, ruby_aot_compile;
PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3);
PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2);
Modified: MacRuby/branches/experimental/main.cpp
===================================================================
--- MacRuby/branches/experimental/main.cpp 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/main.cpp 2009-05-20 05:53:09 UTC (rev 1578)
@@ -7,6 +7,8 @@
#undef RUBY_EXPORT
#include "ruby.h"
+#include "ruby/node.h"
+#include "roxor.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
@@ -23,7 +25,15 @@
try {
ruby_sysinit(&argc, &argv);
ruby_init();
- rb_exit(ruby_run_node(ruby_options(argc, argv)));
+ void *node = ruby_options(argc, argv);
+ assert(node != NULL);
+ if (ruby_aot_compile) {
+ rb_vm_aot_compile((NODE *)node);
+ rb_exit(0);
+ }
+ else {
+ rb_exit(ruby_run_node(node));
+ }
}
catch (...) {
rb_vm_print_current_exception();
Modified: MacRuby/branches/experimental/rakelib/builder.rb
===================================================================
--- MacRuby/branches/experimental/rakelib/builder.rb 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/rakelib/builder.rb 2009-05-20 05:53:09 UTC (rev 1578)
@@ -83,7 +83,7 @@
INSTALL_NAME = File.join(FRAMEWORK_USR_LIB, 'lib' + RUBY_SO_NAME + '.dylib')
ARCHFLAGS = ARCHS.map { |a| '-arch ' + a }.join(' ')
-LLVM_MODULES = "core jit nativecodegen interpreter"
+LLVM_MODULES = "core jit nativecodegen interpreter bitwriter"
CFLAGS = "-I. -I./include -I/usr/include/libxml2 #{ARCHFLAGS} -fno-common -pipe -O3 -g -Wall -fexceptions"
CFLAGS << " -Wno-parentheses -Wno-deprecated-declarations -Werror" if NO_WARN_BUILD
OBJC_CFLAGS = CFLAGS + " -fobjc-gc-only"
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/roxor.cpp 2009-05-20 05:53:09 UTC (rev 1578)
@@ -24,9 +24,12 @@
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/IRBuilder.h>
#include <llvm/Intrinsics.h>
+#include <llvm/Bitcode/ReaderWriter.h>
using namespace llvm;
#include <stack>
+#include <iostream>
+#include <fstream>
#if ROXOR_COMPILER_DEBUG
# include <mach/mach.h>
@@ -192,10 +195,11 @@
static RoxorCompiler *shared;
RoxorCompiler(const char *fname);
+ virtual ~RoxorCompiler(void) { }
Value *compile_node(NODE *node);
- Function *compile_main_function(NODE *node);
+ virtual Function *compile_main_function(NODE *node);
Function *compile_read_attr(ID name);
Function *compile_write_attr(ID name);
Function *compile_stub(const char *types, int argc, bool is_objc);
@@ -209,12 +213,13 @@
const Type *convert_type(const char *type);
- private:
+ protected:
const char *fname;
std::map<ID, Value *> lvars;
std::vector<ID> dvars;
std::map<ID, int *> ivar_slots_cache;
+ std::map<std::string, GlobalVariable *> static_strings;
#if ROXOR_COMPILER_DEBUG
int level;
@@ -323,14 +328,16 @@
abort();
}
- Instruction *compile_const_pointer(void *ptr, bool insert_to_bb=true) {
+ virtual Instruction *
+ compile_const_pointer(void *ptr, bool insert_to_bb=true) {
Value *ptrint = ConstantInt::get(IntTy, (long)ptr);
return insert_to_bb
? new IntToPtrInst(ptrint, PtrTy, "", bb)
: new IntToPtrInst(ptrint, PtrTy, "");
}
- Instruction *compile_const_pointer_to_pointer(void *ptr, bool insert_to_bb=true) {
+ Instruction *
+ compile_const_pointer_to_pointer(void *ptr, bool insert_to_bb=true) {
Value *ptrint = ConstantInt::get(IntTy, (long)ptr);
return insert_to_bb
? new IntToPtrInst(ptrint, PtrPtrTy, "", bb)
@@ -368,6 +375,11 @@
Value *compile_dvar_slot(ID name);
void compile_break_val(Value *val);
Value *compile_jump(NODE *node);
+ virtual Value *compile_mcache(SEL sel, bool super);
+ virtual Instruction *compile_sel(SEL sel, bool add_to_bb=true) {
+ return compile_const_pointer(sel, add_to_bb);
+ }
+ GlobalVariable *compile_const_global_string(const char *str);
void compile_landing_pad_header(void);
void compile_landing_pad_footer(void);
@@ -414,6 +426,31 @@
SEL mid_to_sel(ID mid, int arity);
};
+class RoxorAOTCompiler : public RoxorCompiler
+{
+ public:
+ RoxorAOTCompiler(const char *fname) : RoxorCompiler(fname) { }
+
+ Function *compile_main_function(NODE *node);
+
+ private:
+ std::map<SEL, GlobalVariable *> mcaches;
+ std::map<SEL, GlobalVariable *> sels;
+
+ Value *compile_mcache(SEL sel, bool super);
+ Instruction *compile_sel(SEL sel, bool add_to_bb=true);
+
+ Instruction *
+ compile_const_pointer(void *ptr, bool insert_to_bb=true) {
+ if (ptr == NULL) {
+ return RoxorCompiler::compile_const_pointer(ptr, insert_to_bb);
+ }
+ printf("compile_const_pointer() called with a non-NULL pointer " \
+ "on the AOT compiler - leaving the ship!\n");
+ abort();
+ }
+};
+
llvm::Module *RoxorCompiler::module = NULL;
RoxorCompiler *RoxorCompiler::shared = NULL;
@@ -649,6 +686,7 @@
RoxorVM(void);
+ void optimize(Function *func);
IMP compile(Function *func);
VALUE interpret(Function *func);
@@ -909,10 +947,9 @@
Value *condVal;
if (comparedToVal != NULL) {
std::vector<Value *> params;
- void *eqq_cache = GET_VM()->method_cache_get(selEqq, false);
- params.push_back(compile_const_pointer(eqq_cache));
+ params.push_back(compile_mcache(selEqq, false));
params.push_back(subnodeVal);
- params.push_back(compile_const_pointer((void *)selEqq));
+ params.push_back(compile_sel(selEqq));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, 1));
@@ -1061,10 +1098,8 @@
RubyObjTy, PtrTy, RubyObjTy, RubyObjTy, NULL));
}
- void *eqq_cache = GET_VM()->method_cache_get(selEqq, false);
-
std::vector<Value *> params;
- params.push_back(compile_const_pointer(eqq_cache));
+ params.push_back(compile_mcache(selEqq, false));
params.push_back(selfVal);
params.push_back(comparedToVal);
@@ -1084,9 +1119,8 @@
RubyObjTy, RubyObjTy, NULL));
}
- void *eqq_cache = GET_VM()->method_cache_get(selEqq, false);
std::vector<Value *> params;
- params.push_back(compile_const_pointer(eqq_cache));
+ params.push_back(compile_mcache(selEqq, false));
GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(selEqq, true);
params.push_back(new LoadInst(is_redefined, "", bb));
params.push_back(comparedToVal);
@@ -1095,7 +1129,102 @@
return compile_protected_call(whenSplatFunc, params);
}
+GlobalVariable *
+RoxorCompiler::compile_const_global_string(const char *str)
+{
+ std::string s(str);
+ std::map<std::string, GlobalVariable *>::iterator iter =
+ static_strings.find(s);
+ GlobalVariable *gvar;
+ if (iter == static_strings.end()) {
+ const size_t str_len = strlen(str);
+ assert(str_len > 0);
+
+ const ArrayType *str_type = ArrayType::get(Type::Int8Ty, str_len + 1);
+
+ std::vector<Constant *> ary_elements;
+ for (unsigned int i = 0; i < str_len; i++) {
+ ary_elements.push_back(ConstantInt::get(Type::Int8Ty, str[i]));
+ }
+ ary_elements.push_back(ConstantInt::get(Type::Int8Ty, 0));
+
+ gvar = new GlobalVariable(
+ str_type,
+ true,
+ GlobalValue::InternalLinkage,
+ ConstantArray::get(str_type, ary_elements),
+ std::string("global_string.") + str,
+ RoxorCompiler::module);
+
+ static_strings[s] = gvar;
+ }
+ else {
+ gvar = iter->second;
+ }
+
+ return gvar;
+}
+
Value *
+RoxorCompiler::compile_mcache(SEL sel, bool super)
+{
+ struct mcache *cache = GET_VM()->method_cache_get(sel, super);
+ return compile_const_pointer(cache);
+}
+
+Value *
+RoxorAOTCompiler::compile_mcache(SEL sel, bool super)
+{
+ GlobalVariable *gvar;
+ if (super) {
+ abort(); // TODO
+ }
+ else {
+ std::map<SEL, GlobalVariable *>::iterator iter =
+ mcaches.find(sel);
+ if (iter == mcaches.end()) {
+ gvar = new GlobalVariable(
+ PtrTy,
+ false,
+ GlobalValue::InternalLinkage,
+ Constant::getNullValue(PtrTy),
+ std::string("mcache_") + sel_getName(sel),
+ RoxorCompiler::module);
+ assert(gvar != NULL);
+ mcaches[sel] = gvar;
+ }
+ else {
+ gvar = iter->second;
+ }
+ }
+ return new LoadInst(gvar, "", bb);
+}
+
+Instruction *
+RoxorAOTCompiler::compile_sel(SEL sel, bool add_to_bb)
+{
+ std::map<SEL, GlobalVariable *>::iterator iter = sels.find(sel);
+ GlobalVariable *gvar;
+ if (iter == sels.end()) {
+ gvar = new GlobalVariable(
+ PtrTy,
+ false,
+ GlobalValue::InternalLinkage,
+ Constant::getNullValue(PtrTy),
+ std::string("sel_") + sel_getName(sel),
+ RoxorCompiler::module);
+ assert(gvar != NULL);
+ sels[sel] = gvar;
+ }
+ else {
+ gvar = iter->second;
+ }
+ return add_to_bb
+ ? new LoadInst(gvar, "", bb)
+ : new LoadInst(gvar, "");
+}
+
+Value *
RoxorCompiler::compile_dispatch_call(std::vector<Value *> ¶ms)
{
if (dispatcherFunc == NULL) {
@@ -1144,10 +1273,9 @@
std::vector<Value *> params;
const SEL sel = mid_to_sel(mid, argc);
- void *cache = GET_VM()->method_cache_get(sel, false);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(sel, false));
params.push_back(recv);
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, argc));
@@ -2460,10 +2588,9 @@
bb = thenBB;
std::vector<Value *> new_params;
- void *cache = GET_VM()->method_cache_get(new_sel, false);
- new_params.push_back(compile_const_pointer(cache));
+ new_params.push_back(compile_mcache(new_sel, false));
new_params.push_back(params[1]);
- new_params.push_back(compile_const_pointer((void *)new_sel));
+ new_params.push_back(compile_sel(new_sel));
new_params.push_back(params[3]);
new_params.push_back(params[4]);
new_params.push_back(ConstantInt::get(Type::Int32Ty, argc - 1));
@@ -2774,6 +2901,12 @@
return s;
}
+inline void
+RoxorVM::optimize(Function *func)
+{
+ fpm->run(*func);
+}
+
IMP
RoxorVM::compile(Function *func)
{
@@ -2786,10 +2919,8 @@
uint64_t start = mach_absolute_time();
#endif
- // Optimize.
- fpm->run(*func);
-
- // Compile.
+ // Optimize & compile.
+ optimize(func);
IMP imp = (IMP)ee->getPointerToFunction(func);
#if ROXOR_COMPILER_DEBUG
@@ -2900,6 +3031,13 @@
return iter->second;
}
+extern "C"
+void *
+rb_vm_get_method_cache(SEL sel)
+{
+ return GET_VM()->method_cache_get(sel, false);
+}
+
inline struct RoxorFunctionIMP *
RoxorVM::method_func_imp_get(IMP imp)
{
@@ -3594,10 +3732,9 @@
assert(node->nd_next->nd_vid > 0);
sel = mid_to_sel(node->nd_next->nd_vid, 0);
}
- void *cache = GET_VM()->method_cache_get(sel, false);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(sel, false));
params.push_back(recv);
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
@@ -3653,11 +3790,10 @@
ID mid = nd_type(node) == NODE_OP_ASGN1
? node->nd_mid : node->nd_next->nd_mid;
sel = mid_to_sel(mid, 1);
- cache = GET_VM()->method_cache_get(sel, false);
params.clear();
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(sel, false));
params.push_back(tmp);
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, 1));
@@ -3678,11 +3814,10 @@
assert(node->nd_next->nd_aid > 0);
sel = mid_to_sel(node->nd_next->nd_aid, 1);
}
- cache = GET_VM()->method_cache_get(sel, false);
params.clear();
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(sel, false));
params.push_back(recv);
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
argc++;
@@ -3727,10 +3862,9 @@
}
std::vector<Value *> params;
- void *cache = GET_VM()->method_cache_get(selBackquote, false);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(selBackquote, false));
params.push_back(nilVal);
- params.push_back(compile_const_pointer((void *)selBackquote));
+ params.push_back(compile_sel(selBackquote));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, 1));
@@ -4113,15 +4247,14 @@
// Method cache.
const SEL sel = mid_to_sel(mid, positive_arity ? 1 : 0);
- void *cache = GET_VM()->method_cache_get(sel, super_call);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(sel, super_call));
// Self.
params.push_back(recv == NULL ? current_self
: compile_node(recv));
// Selector.
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
// RubySpec requires that we compile the block *after* the
// arguments, so we do pass NULL as the block for the moment.
@@ -4450,10 +4583,9 @@
}
std::vector<Value *> params;
- void *cache = GET_VM()->method_cache_get(selEqTilde, false);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(selEqTilde, false));
params.push_back(reTarget);
- params.push_back(compile_const_pointer((void *)selEqTilde));
+ params.push_back(compile_sel(selEqTilde));
params.push_back(compile_const_pointer(NULL));
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, 1));
@@ -4565,7 +4697,7 @@
rb_vm_arity_t arity = rb_vm_node_arity(body);
const SEL sel = mid_to_sel(mid, arity.real);
- params.push_back(compile_const_pointer((void *)sel));
+ params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(new_function));
rb_objc_retain((void *)body);
@@ -4983,10 +5115,9 @@
// dispatch #each on the receiver
std::vector<Value *> params;
- void *cache = GET_VM()->method_cache_get(selEach, false);
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_mcache(selEach, false));
params.push_back(compile_node(node->nd_iter));
- params.push_back(compile_const_pointer((void *)selEach));
+ params.push_back(compile_sel(selEach));
params.push_back(compile_block_create());
params.push_back(ConstantInt::get(Type::Int8Ty, 0));
params.push_back(ConstantInt::get(Type::Int32Ty, 0));
@@ -5127,6 +5258,79 @@
}
Function *
+RoxorAOTCompiler::compile_main_function(NODE *node)
+{
+ Function *function = RoxorCompiler::compile_main_function(node);
+
+ BasicBlock::InstListType &list =
+ function->getEntryBlock().getInstList();
+
+ // Compile method caches.
+
+ Function *getCacheFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_get_method_cache",
+ PtrTy, PtrTy, NULL));
+
+ for (std::map<SEL, GlobalVariable *>::iterator i = mcaches.begin();
+ i != mcaches.end();
+ ++i) {
+
+ SEL sel = i->first;
+ GlobalVariable *gvar = i->second;
+
+ std::vector<Value *> params;
+ Instruction *load = compile_sel(sel, false);
+ params.push_back(load);
+
+ Instruction *call = CallInst::Create(getCacheFunc, params.begin(),
+ params.end(), "");
+
+ Instruction *assign = new StoreInst(call, gvar, "");
+
+ list.insert(list.begin(), assign);
+ list.insert(list.begin(), call);
+ list.insert(list.begin(), load);
+ }
+
+ // Compile selectors.
+
+ Function *registerSelFunc = cast<Function>(module->getOrInsertFunction(
+ "sel_registerName",
+ PtrTy, PtrTy, NULL));
+
+ for (std::map<SEL, GlobalVariable *>::iterator i = sels.begin();
+ i != sels.end();
+ ++i) {
+
+ SEL sel = i->first;
+ GlobalVariable *gvar = i->second;
+
+ GlobalVariable *sel_gvar =
+ compile_const_global_string(sel_getName(sel));
+
+ std::vector<Value *> idxs;
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ Instruction *load = GetElementPtrInst::Create(sel_gvar,
+ idxs.begin(), idxs.end(), "");
+
+ std::vector<Value *> params;
+ params.push_back(load);
+
+ Instruction *call = CallInst::Create(registerSelFunc, params.begin(),
+ params.end(), "");
+
+ Instruction *assign = new StoreInst(call, gvar, "");
+
+ list.insert(list.begin(), assign);
+ list.insert(list.begin(), call);
+ list.insert(list.begin(), load);
+ }
+
+ return function;
+}
+
+Function *
RoxorCompiler::compile_read_attr(ID name)
{
Function *f = cast<Function>(module->getOrInsertFunction("",
@@ -9047,6 +9251,16 @@
return 0;
}
+static inline void
+__init_shared_compiler(void)
+{
+ if (RoxorCompiler::shared == NULL) {
+ RoxorCompiler::shared = ruby_aot_compile
+ ? new RoxorAOTCompiler("")
+ : new RoxorCompiler("");
+ }
+}
+
extern "C"
VALUE
rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
@@ -9056,6 +9270,7 @@
GET_VM()->bindings.push_back(binding);
}
+ __init_shared_compiler();
Function *function = RoxorCompiler::shared->compile_main_function(node);
if (binding != NULL) {
@@ -9102,6 +9317,108 @@
}
extern "C"
+void
+rb_vm_aot_compile(NODE *node)
+{
+ assert(ruby_aot_compile);
+
+ // Compile the program as IR.
+ __init_shared_compiler();
+ Function *f = RoxorCompiler::shared->compile_main_function(node);
+ f->setName("rb_main");
+ GET_VM()->optimize(f);
+
+ // Save the bitcode into a temporary file.
+ const char *tmpdir = getenv("TMPDIR");
+ assert(tmpdir != NULL);
+ std::string bc_path(tmpdir);
+ bc_path.append("ruby.bc");
+ std::ofstream out(bc_path.c_str());
+ WriteBitcodeToFile(RoxorCompiler::module, out);
+ out.close();
+
+ // Compile the bitcode as assembly.
+ std::string llc_line("llc -f ");
+ llc_line.append(bc_path);
+ llc_line.append(" -o=");
+ std::string as_path(tmpdir);
+ as_path.append("ruby.s");
+ llc_line.append(as_path);
+ if (system(llc_line.c_str()) != 0) {
+ printf("error when compiling bitcode as assembly\n" \
+ "line was: %s", llc_line.c_str());
+ exit(1);
+ }
+
+ // Compile the assembly.
+ std::string gcc_line("gcc -c -arch x86_64 ");
+ gcc_line.append(as_path);
+ std::string o_path(tmpdir);
+ o_path.append("ruby.o");
+ gcc_line.append(" -o ");
+ gcc_line.append(o_path);
+ if (system(gcc_line.c_str()) != 0) {
+ printf("error when compiling assembly as machine code\n" \
+ "line was: %s", gcc_line.c_str());
+ exit(1);
+ }
+
+ // Compile main function.
+ std::string main_path(tmpdir);
+ main_path.append("main.c");
+ std::ofstream main_file(main_path.c_str());
+ std::string main_content(
+"extern void ruby_sysinit(int *, char ***);\n"
+"extern void ruby_init(void);\n"
+"extern void ruby_set_argv(int, char **);\n"
+"extern void *rb_vm_top_self(void);\n"
+"extern void *rb_main(void *, void *);\n"
+"\n"
+"int main(int argc, char **argv)\n"
+"{\n"
+" ruby_sysinit(&argc, &argv);\n"
+" ruby_init();\n"
+" ruby_set_argv(argc, argv);\n"
+" rb_main(rb_vm_top_self(), 0);\n"
+" return 1;\n"
+"}\n"
+);
+ main_file.write(main_content.c_str(), main_content.size());
+ main_file.close();
+ gcc_line.clear();
+ gcc_line.append("gcc ");
+ gcc_line.append(main_path);
+ gcc_line.append(" -c -arch x86_64 -o ");
+ std::string main_o_path(tmpdir);
+ main_o_path.append("main.o");
+ gcc_line.append(main_o_path);
+ if (system(gcc_line.c_str()) != 0) {
+ printf("error when compiling main function as machine code\n" \
+ "line was: %s", gcc_line.c_str());
+ exit(1);
+ }
+
+ // Link everything!
+ std::string out_path("a.out");
+ gcc_line.clear();
+ gcc_line.append("g++ ");
+ gcc_line.append(o_path);
+ gcc_line.append(" -o ");
+ gcc_line.append(out_path);
+ // XXX -L. should be removed later
+ gcc_line.append(" -L. -lmacruby-static -arch x86_64 -framework Foundation -lobjc -lauto -I/usr/include/libxml2 -lxml2 `llvm-config --ldflags --libs core jit nativecodegen interpreter bitwriter` ");
+ gcc_line.append(main_o_path);
+ if (system(gcc_line.c_str()) != 0) {
+ printf("error when compiling main function as machine code\n" \
+ "line was: %s", gcc_line.c_str());
+ exit(1);
+ }
+
+ // TODO: dump IR -> llvm-as -> llc -> gcc
+// RoxorCompiler::module->dump();
+}
+
+extern "C"
VALUE
rb_vm_top_self(void)
{
@@ -10651,8 +10968,6 @@
void
Init_VM(void)
{
- RoxorCompiler::shared = new RoxorCompiler("");
-
rb_cTopLevel = rb_define_class("TopLevel", rb_cObject);
rb_objc_define_method(rb_cTopLevel, "to_s", (void *)rb_toplevel_to_s, 0);
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/roxor.h 2009-05-20 05:53:09 UTC (rev 1578)
@@ -56,6 +56,7 @@
bool try_interpreter);
VALUE rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
rb_vm_binding_t *binding, bool try_interpreter);
+void rb_vm_aot_compile(NODE *node);
bool rb_vm_running(void);
void rb_vm_set_running(bool flag);
Modified: MacRuby/branches/experimental/ruby.c
===================================================================
--- MacRuby/branches/experimental/ruby.c 2009-05-19 22:55:11 UTC (rev 1577)
+++ MacRuby/branches/experimental/ruby.c 2009-05-20 05:53:09 UTC (rev 1578)
@@ -44,6 +44,7 @@
/* TODO: move to VM */
VALUE ruby_debug = Qfalse;
VALUE ruby_verbose = Qfalse;
+VALUE ruby_aot_compile = Qfalse;
VALUE rb_parser_get_yydebug(VALUE);
VALUE rb_parser_set_yydebug(VALUE, VALUE);
@@ -131,6 +132,7 @@
"-x[directory] strip off text before #!ruby line and perhaps cd to directory",
"--copyright print the copyright",
"--version print the version",
+ "--compile ahead-of-time (AOT) compile the script",
NULL
};
const char *const *p = usage_msg;
@@ -696,8 +698,9 @@
goto switch_end;
}
s++;
- if (strcmp("copyright", s) == 0)
+ if (strcmp("copyright", s) == 0) {
opt->copyright = 1;
+ }
else if (strcmp("debug", s) == 0) {
ruby_debug = Qtrue;
ruby_verbose = Qtrue;
@@ -727,14 +730,16 @@
encoding:
opt->ext.enc.name = rb_str_new2(s);
}
- else if (strcmp("version", s) == 0)
+ else if (strcmp("version", s) == 0) {
opt->version = 1;
+ }
else if (strcmp("verbose", s) == 0) {
opt->verbose = 1;
ruby_verbose = Qtrue;
}
- else if (strcmp("yydebug", s) == 0)
+ else if (strcmp("yydebug", s) == 0) {
opt->yydebug = 1;
+ }
else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) {
if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break;
ruby_each_words(s, dump_option, &opt->dump);
@@ -743,6 +748,9 @@
usage(origarg.argv[0]);
rb_exit(EXIT_SUCCESS);
}
+ else if (strcmp("compile", s) == 0) {
+ ruby_aot_compile = Qtrue;
+ }
else {
rb_raise(rb_eRuntimeError,
"invalid option --%s (-h will show valid options)", s);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090519/226f34a4/attachment-0001.html>
More information about the macruby-changes
mailing list