[macruby-changes] [1421] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Wed Apr 15 22:28:38 PDT 2009
Revision: 1421
http://trac.macosforge.org/projects/ruby/changeset/1421
Author: lsansonetti at apple.com
Date: 2009-04-15 22:28:37 -0700 (Wed, 15 Apr 2009)
Log Message:
-----------
more work on the stub system (still a work in progress, though)
Modified Paths:
--------------
MacRuby/branches/experimental/objc.h
MacRuby/branches/experimental/objc.m
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/objc.h
===================================================================
--- MacRuby/branches/experimental/objc.h 2009-04-16 05:16:53 UTC (rev 1420)
+++ MacRuby/branches/experimental/objc.h 2009-04-16 05:28:37 UTC (rev 1421)
@@ -74,6 +74,72 @@
bool rb_objc_symbolize_address(void *addr, void **start, char *name, size_t name_len);
+static inline int
+SubtypeUntil(const char *type, char end)
+{
+ int level = 0;
+ const char *head = type;
+
+ while (*type)
+ {
+ if (!*type || (!level && (*type == end)))
+ return (int)(type - head);
+
+ switch (*type)
+ {
+ case ']': case '}': case ')': level--; break;
+ case '[': case '{': case '(': level += 1; break;
+ }
+
+ type += 1;
+ }
+
+ rb_bug ("Object: SubtypeUntil: end of type encountered prematurely\n");
+ return 0;
+}
+
+static inline const char *
+SkipStackSize(const char *type)
+{
+ while ((*type >= '0') && (*type <= '9')) {
+ type += 1;
+ }
+ return type;
+}
+
+static inline const char *
+SkipFirstType(const char *type)
+{
+ while (1) {
+ switch (*type++) {
+ case 'O': /* bycopy */
+ case 'n': /* in */
+ case 'o': /* out */
+ case 'N': /* inout */
+ case 'r': /* const */
+ case 'V': /* oneway */
+ case '^': /* pointers */
+ break;
+
+ /* arrays */
+ case '[':
+ return type + SubtypeUntil (type, ']') + 1;
+
+ /* structures */
+ case '{':
+ return type + SubtypeUntil (type, '}') + 1;
+
+ /* unions */
+ case '(':
+ return type + SubtypeUntil (type, ')') + 1;
+
+ /* basic types */
+ default:
+ return type;
+ }
+ }
+}
+
#if defined(__cplusplus)
}
#endif
Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m 2009-04-16 05:16:53 UTC (rev 1420)
+++ MacRuby/branches/experimental/objc.m 2009-04-16 05:28:37 UTC (rev 1421)
@@ -1059,72 +1059,6 @@
}
#endif
-static inline int
-SubtypeUntil(const char *type, char end)
-{
- int level = 0;
- const char *head = type;
-
- while (*type)
- {
- if (!*type || (!level && (*type == end)))
- return (int)(type - head);
-
- switch (*type)
- {
- case ']': case '}': case ')': level--; break;
- case '[': case '{': case '(': level += 1; break;
- }
-
- type += 1;
- }
-
- rb_bug ("Object: SubtypeUntil: end of type encountered prematurely\n");
- return 0;
-}
-
-static inline const char *
-SkipStackSize(const char *type)
-{
- while ((*type >= '0') && (*type <= '9')) {
- type += 1;
- }
- return type;
-}
-
-static inline const char *
-SkipFirstType(const char *type)
-{
- while (1) {
- switch (*type++) {
- case 'O': /* bycopy */
- case 'n': /* in */
- case 'o': /* out */
- case 'N': /* inout */
- case 'r': /* const */
- case 'V': /* oneway */
- case '^': /* pointers */
- break;
-
- /* arrays */
- case '[':
- return type + SubtypeUntil (type, ']') + 1;
-
- /* structures */
- case '{':
- return type + SubtypeUntil (type, '}') + 1;
-
- /* unions */
- case '(':
- return type + SubtypeUntil (type, ')') + 1;
-
- /* basic types */
- default:
- return type;
- }
- }
-}
-
static inline void
rb_method_setTypeEncoding(Method method, const char *types)
{
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-16 05:16:53 UTC (rev 1420)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-16 05:28:37 UTC (rev 1421)
@@ -186,6 +186,7 @@
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);
private:
const char *fname;
@@ -325,6 +326,9 @@
void compile_rethrow_exception(void);
Value *compile_lvar_slot(ID name);
+ Value *compile_conversion_to_c(const char *type, Value *val, Value *slot);
+ Value *compile_conversion_to_ruby(const char *type, Value *val);
+
int *get_slot_cache(ID id) {
if (current_block || !current_instance_method || current_module) {
return NULL;
@@ -347,6 +351,7 @@
BasicBlock::InstListType::iterator iter);
bool unbox_ruby_constant(Value *val, VALUE *rval);
SEL mid_to_sel(ID mid, int arity);
+ const Type *convert_type(const char *type);
};
llvm::Module *RoxorCompiler::module = NULL;
@@ -452,7 +457,7 @@
std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
std::vector<jmp_buf *> return_from_block_jmp_bufs;
- std::map<std::string, void *> stubs;
+ std::map<std::string, void *> c_stubs, objc_stubs;
#if ROXOR_ULTRA_LAZY_JIT
std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
@@ -4699,7 +4704,210 @@
return f;
}
+static inline const char *
+GetFirstType(const char *p, char *buf, size_t buflen)
+{
+ const char *p2 = SkipFirstType(p);
+ const size_t len = p2 - p;
+ assert(len < buflen);
+ strncpy(buf, p, len);
+ buf[len] = '\0';
+ return p2;
+}
+
+static inline void
+convert_error(const char type, VALUE val)
+{
+ rb_raise(rb_eTypeError,
+ "cannot convert object `%s' (%s) to Objective-C type `%c'",
+ RSTRING_PTR(rb_inspect(val)),
+ rb_obj_classname(val),
+ type);
+}
+
+extern "C"
+void
+rb_vm_rval_to_ocval(VALUE val, void **ocval)
+{
+ *(id *)ocval = val == Qnil ? NULL : RB2OC(val);
+}
+
+extern "C"
+void
+rb_vm_rval_to_ocsel(VALUE rval, void **ocval)
+{
+ if (NIL_P(rval)) {
+ *(SEL *)ocval = NULL;
+ }
+ else {
+ const char *cstr;
+
+ switch (TYPE(rval)) {
+ case T_STRING:
+ cstr = StringValuePtr(rval);
+ break;
+
+ case T_SYMBOL:
+ cstr = rb_sym2name(rval);
+ break;
+
+ default:
+ convert_error(_C_SEL, rval);
+ }
+ *(SEL *)ocval = sel_registerName(cstr);
+ }
+}
+
Value *
+RoxorCompiler::compile_conversion_to_c(const char *type, Value *val, Value *slot)
+{
+ const char *func_name = NULL;
+
+ switch (*type) {
+ case _C_ID:
+ case _C_CLASS:
+ func_name = "rb_vm_rval_to_ocval";
+ break;
+
+ case _C_SEL:
+ func_name = "rb_vm_rval_to_ocsel";
+ break;
+
+ default:
+ printf("unrecognized compile type `%s' to C - aborting\n", type);
+ abort();
+ }
+
+ std::vector<Value *> params;
+ params.push_back(val);
+ params.push_back(new BitCastInst(slot, PtrTy, "", bb));
+
+ Function *func = cast<Function>(module->getOrInsertFunction(
+ func_name, Type::VoidTy, RubyObjTy, PtrTy, NULL));
+
+ CallInst::Create(func, params.begin(), params.end(), "", bb);
+ return new LoadInst(slot, "", bb);
+}
+
+Value *
+RoxorCompiler::compile_conversion_to_ruby(const char *type, Value *val)
+{
+ // TODO
+ return val;
+}
+
+inline const Type *
+RoxorCompiler::convert_type(const char *type)
+{
+ switch (*type) {
+ case _C_ID:
+ case _C_CLASS:
+ return RubyObjTy;
+
+ case _C_SEL:
+ case _C_CHARPTR:
+ case _C_PTR:
+ return PtrTy;
+
+ case _C_BOOL:
+ case _C_UCHR:
+ case _C_CHR:
+ return Type::Int8Ty;
+
+ case _C_SHT:
+ case _C_USHT:
+ return Type::Int16Ty;
+
+ case _C_INT:
+ case _C_UINT:
+ return Type::Int32Ty;
+
+ case _C_LNG:
+#if __LP64__
+ return Type::Int64Ty;
+#else
+ return Type::Int32Ty;
+#endif
+
+ case _C_FLT:
+ return Type::FloatTy;
+
+ case _C_DBL:
+ return Type::DoubleTy;
+ }
+
+ printf("unrecognized runtime type `%s' - aborting\n", type);
+ abort();
+}
+
+Function *
+RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
+{
+ assert(is_objc); // for now
+
+ // VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+ // {
+ // return (*imp)(self, sel, argv[0], argv[1], ...);
+ // }
+ Function *f = cast<Function>(module->getOrInsertFunction("",
+ RubyObjTy, PtrTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
+ NULL));
+
+ bb = BasicBlock::Create("EntryBlock", f);
+
+ Function::arg_iterator arg = f->arg_begin();
+ Value *imp_arg = arg++;
+ Value *self_arg = arg++;
+ Value *sel_arg = arg++;
+ /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
+ Value *argv_arg = arg++;
+
+ std::vector<const Type *> f_types;
+ std::vector<Value *> params;
+
+ char buf[100];
+ const char *p = SkipFirstType(types); // skip retval
+
+ // self
+ p = SkipFirstType(p);
+ f_types.push_back(RubyObjTy);
+ params.push_back(self_arg);
+ // sel
+ p = SkipFirstType(p);
+ f_types.push_back(PtrTy);
+ params.push_back(sel_arg);
+
+ // Arguments.
+ for (int i = 0; i < argc; i++) {
+ p = GetFirstType(p, buf, sizeof buf);
+ //printf("arg[%d] type `%s'\n", i, buf);
+
+ f_types.push_back(convert_type(buf));
+
+ Value *index = ConstantInt::get(Type::Int32Ty, i);
+ Value *slot = GetElementPtrInst::Create(argv_arg, index, "", bb);
+ Value *arg_val = new LoadInst(slot, "", bb);
+ Value *new_val_slot = new AllocaInst(f_types[i + 2], "", bb);
+
+ params.push_back(compile_conversion_to_c(buf, arg_val, new_val_slot));
+ }
+
+ // Appropriately cast the IMP argument.
+ FunctionType *ft = FunctionType::get(RubyObjTy, f_types, false);
+ Value *imp = new BitCastInst(imp_arg, PointerType::getUnqual(ft), "", bb);
+
+ // Compile call.
+ CallInst *imp_call = CallInst::Create(imp, params.begin(), params.end(), "", bb);
+
+ // Compile retval.
+ GetFirstType(types, buf, sizeof buf);
+ Value *retval = compile_conversion_to_ruby(buf, imp_call);
+ ReturnInst::Create(retval, bb);
+
+ return f;
+}
+
+Value *
RoxorCompiler::compile_lvar_slot(ID name)
{
std::map<ID, Value *>::iterator iter = lvars.find(name);
@@ -5895,14 +6103,22 @@
}
static void *
-vm_gen_stub(std::string types, int argc, bool is_objc)
+vm_gen_stub(const char *types, int argc, bool is_objc)
{
- std::map<std::string, void *>::iterator iter = GET_VM()->stubs.find(types);
- if (iter != GET_VM()->stubs.end()) {
+ std::map<std::string, void *> &stubs =
+ is_objc ? GET_VM()->objc_stubs : GET_VM()->c_stubs;
+ std::map<std::string, void *>::iterator iter = stubs.find(types);
+ if (iter != stubs.end()) {
return iter->second;
}
-printf("vm_gen_stub %s\n", types.c_str());
- return NULL;
+
+ //printf("generating %s stub %s argc %d\n", is_objc ? "objc" : "c", types, argc);
+
+ Function *f = RoxorCompiler::shared->compile_stub(types, argc, is_objc);
+ void *stub = (void *)GET_VM()->compile(f);
+ stubs.insert(std::make_pair(types, stub));
+
+ return stub;
}
__attribute__((always_inline))
@@ -7229,7 +7445,7 @@
}
static VALUE
-builtin_stub1(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+builtin_ostub1(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
{
return ((VALUE (*)(VALUE, SEL))*imp)(self, sel);
}
@@ -7237,8 +7453,8 @@
static void
setup_builtin_stubs(void)
{
- GET_VM()->stubs.insert(std::make_pair("@@:", (void *)builtin_stub1));
- GET_VM()->stubs.insert(std::make_pair("#@:", (void *)builtin_stub1));
+ GET_VM()->objc_stubs.insert(std::make_pair("@@:", (void *)builtin_ostub1));
+ GET_VM()->objc_stubs.insert(std::make_pair("#@:", (void *)builtin_ostub1));
}
#if ROXOR_ULTRA_LAZY_JIT
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090415/2714a601/attachment-0001.html>
More information about the macruby-changes
mailing list