Permalink
Browse files

fixed variadic functions/methods calls

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2694 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent ef050fa commit 9fab1acf1ac5c99fbf72e653930d7f43ebfdd9d7 @lrz lrz committed Oct 1, 2009
Showing with 43 additions and 18 deletions.
  1. +2 −2 bridgesupport.cpp
  2. +6 −5 compiler.cpp
  3. +2 −1 compiler.h
  4. +1 −1 sprintf.cpp
  5. +30 −8 vm.cpp
  6. +2 −1 vm.h
View
@@ -1300,8 +1300,8 @@ rb_ffi_attach_function(VALUE rcv, SEL sel, VALUE name, VALUE args, VALUE ret)
types.append(convert_ffi_type(RARRAY_AT(args, i), true));
}
- rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types, argc,
- false);
+ rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
+ false, argc, false);
Function *f = RoxorCompiler::shared->compile_ffi_function((void *)stub,
sym, argc);
IMP imp = GET_CORE()->compile(f);
View
@@ -6505,7 +6505,8 @@ RoxorCompiler::convert_type(const char *type)
}
Function *
-RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
+RoxorCompiler::compile_stub(const char *types, bool variadic, int min_argc,
+ bool is_objc)
{
Function *f;
@@ -6575,10 +6576,10 @@ RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
// Arguments.
std::vector<unsigned int> byval_args;
int given_argc = 0;
- bool variadic = false;
+ bool stop_arg_type = false;
while ((p = GetFirstType(p, buf, sizeof buf)) != NULL && buf[0] != '\0') {
- if (given_argc == argc) {
- variadic = true;
+ if (variadic && given_argc == min_argc) {
+ stop_arg_type = true;
}
const Type *llvm_type = convert_type(buf);
@@ -6592,7 +6593,7 @@ RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
byval_args.push_back(f_types.size() + 1 /* retval */);
}
- if (!variadic) {
+ if (!stop_arg_type) {
// In order to conform to the ABI, we must stop providing types
// once we start dealing with variable arguments and instead mark
// the function as variadic.
View
@@ -52,7 +52,8 @@ class RoxorCompiler {
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);
+ Function *compile_stub(const char *types, bool variadic, int min_argc,
+ bool is_objc);
Function *compile_bs_struct_new(rb_vm_bs_boxed_t *bs_boxed);
Function *compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed,
int field);
View
@@ -491,7 +491,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
}
rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
- 3, false);
+ true, 3, false);
VALUE str = (*stub)((IMP)&CFStringCreateWithFormat, argc + 3, stub_args);
CFMakeCollectable((void *)str);
View
@@ -2513,16 +2513,22 @@ method_missing(VALUE obj, SEL sel, rb_vm_block_t *block, int argc, const VALUE *
}
void *
-RoxorCore::gen_stub(std::string types, int argc, bool is_objc)
+RoxorCore::gen_stub(std::string types, bool variadic, int min_argc,
+ bool is_objc)
{
lock();
+#if ROXOR_VM_DEBUG
+ printf("gen Ruby -> %s stub with types %s\n", is_objc ? "ObjC" : "C",
+ types.c_str());
+#endif
+
std::map<std::string, void *> &stubs = is_objc ? objc_stubs : c_stubs;
std::map<std::string, void *>::iterator iter = stubs.find(types);
void *stub;
if (iter == stubs.end()) {
- Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
- is_objc);
+ Function *f = RoxorCompiler::shared->compile_stub(types.c_str(),
+ variadic, min_argc, is_objc);
stub = (void *)compile(f);
stubs.insert(std::make_pair(types, stub));
}
@@ -2570,11 +2576,24 @@ RoxorCore::gen_to_ocval_convertor(std::string type)
}
static inline void
-vm_gen_bs_func_types(bs_element_function_t *bs_func, std::string &types)
+vm_gen_bs_func_types(int argc, const VALUE *argv,
+ bs_element_function_t *bs_func, std::string &types)
{
types.append(bs_func->retval == NULL ? "v" : bs_func->retval->type);
- for (unsigned i = 0; i < bs_func->args_count; i++) {
+ int printf_arg = -1;
+ for (int i = 0; i < (int)bs_func->args_count; i++) {
types.append(bs_func->args[i].type);
+ if (bs_func->args[i].printf_format) {
+ printf_arg = i;
+ }
+ }
+ if (bs_func->variadic) {
+ // TODO honor printf_format
+// if (printf_arg != -1) {
+// }
+ for (int i = bs_func->args_count; i < argc; i++) {
+ types.append("@");
+ }
}
}
@@ -2692,8 +2711,10 @@ fill_ocache(struct mcache *cache, VALUE self, Class klass, IMP imp, SEL sel,
sel_getName(sel));
abort();
}
+ bool variadic = false;
if (ocache.bs_method != NULL && ocache.bs_method->variadic
&& method != NULL) {
+ // TODO honor printf_format
const int real_argc = method_getNumberOfArguments(method) - 2;
if (real_argc < argc) {
const size_t s = strlen(types);
@@ -2703,8 +2724,9 @@ fill_ocache(struct mcache *cache, VALUE self, Class klass, IMP imp, SEL sel,
}
argc = real_argc;
}
+ variadic = true;
}
- ocache.stub = (rb_vm_objc_stub_t *)GET_CORE()->gen_stub(types,
+ ocache.stub = (rb_vm_objc_stub_t *)GET_CORE()->gen_stub(types, variadic,
argc, true);
}
@@ -2835,14 +2857,14 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name);
if (bs_func != NULL) {
std::string types;
- vm_gen_bs_func_types(bs_func, types);
+ vm_gen_bs_func_types(argc, argv, bs_func, types);
cache->flag = MCACHE_FCALL;
fcache.bs_function = bs_func;
fcache.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
assert(fcache.imp != NULL);
fcache.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
- argc, false);
+ bs_func->variadic, bs_func->args_count, false);
}
else {
// Still nothing, then let's call #method_missing.
View
@@ -638,7 +638,8 @@ class RoxorCore {
// This callback is public for the only reason it's called by C.
void bs_parse_cb(bs_element_type_t type, void *value, void *ctx);
- void *gen_stub(std::string types, int argc, bool is_objc);
+ void *gen_stub(std::string types, bool variadic, int min_argc,
+ bool is_objc);
void *gen_to_rval_convertor(std::string type);
void *gen_to_ocval_convertor(std::string type);

0 comments on commit 9fab1ac

Please sign in to comment.