Revision: 1517 http://trac.macosforge.org/projects/ruby/changeset/1517 Author: lsansonetti@apple.com Date: 2009-05-02 18:02:45 -0700 (Sat, 02 May 2009) Log Message: ----------- adding more overwrite specs + fixed compilation of stubs returning a large struct Modified Paths: -------------- MacRuby/branches/experimental/roxor.cpp MacRuby/branches/experimental/spec/macruby/fixtures/method.m MacRuby/branches/experimental/spec/macruby/fixtures/method.rb MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb Modified: MacRuby/branches/experimental/roxor.cpp =================================================================== --- MacRuby/branches/experimental/roxor.cpp 2009-05-02 20:07:25 UTC (rev 1516) +++ MacRuby/branches/experimental/roxor.cpp 2009-05-03 01:02:45 UTC (rev 1517) @@ -6398,18 +6398,29 @@ { char buf[100]; const char *p = types; + std::vector<const Type *> f_types; + // Return value. p = GetFirstType(p, buf, sizeof buf); std::string ret_type(buf); const Type *f_ret_type = convert_type(buf); + const Type *f_sret_type = NULL; + if (GET_VM()->is_large_struct_type(f_ret_type)) { + // We are returning a large struct, we need to pass a pointer as the + // first argument to the structure data and return void to conform to + // the ABI. + f_types.push_back(PointerType::getUnqual(f_ret_type)); + f_sret_type = f_ret_type; + f_ret_type = Type::VoidTy; + } - std::vector<const Type *> f_types; // self f_types.push_back(RubyObjTy); p = SkipFirstType(p); // sel f_types.push_back(PtrTy); p = SkipFirstType(p); + // Arguments. std::vector<std::string> arg_types; for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) { p = GetFirstType(p, buf, sizeof buf); @@ -6417,31 +6428,44 @@ arg_types.push_back(buf); } + // Create the function. FunctionType *ft = FunctionType::get(f_ret_type, f_types, false); Function *f = cast<Function>(module->getOrInsertFunction("", ft)); Function::arg_iterator arg = f->arg_begin(); bb = BasicBlock::Create("EntryBlock", f); + Value *sret = NULL; + if (f_sret_type != NULL) { + sret = arg++; + f->addAttribute(0, Attribute::StructRet); + } + std::vector<Value *> params; params.push_back(arg++); // self params.push_back(arg++); // sel + // Convert every incoming argument into Ruby type. for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) { Value *ruby_arg = compile_conversion_to_ruby(arg_types[i].c_str(), f_types[i + 2], arg++); params.push_back(ruby_arg); } + // Call the Ruby implementation. Value *ret_val = CallInst::Create(ruby_func, params.begin(), params.end(), "", bb); + // Convert the return value into Objective-C type (if any). if (f_ret_type != Type::VoidTy) { ret_val = compile_conversion_to_c(ret_type.c_str(), ret_val, new AllocaInst(f_ret_type, "", bb)); - ReturnInst::Create(ret_val, bb); } + else if (sret != NULL) { + compile_conversion_to_c(ret_type.c_str(), ret_val, sret); + ReturnInst::Create(bb); + } else { ReturnInst::Create(bb); } Modified: MacRuby/branches/experimental/spec/macruby/fixtures/method.m =================================================================== --- MacRuby/branches/experimental/spec/macruby/fixtures/method.m 2009-05-02 20:07:25 UTC (rev 1516) +++ MacRuby/branches/experimental/spec/macruby/fixtures/method.m 2009-05-03 01:02:45 UTC (rev 1517) @@ -255,51 +255,101 @@ return 3.1415; } ++ (BOOL)testMethodReturningFloat:(TestMethod *)o +{ + return [o methodReturningFloat] == (float)3.1415; +} + - (double)methodReturningDouble { return 3.1415; } ++ (BOOL)testMethodReturningDouble:(TestMethod *)o +{ + return [o methodReturningDouble] == (double)3.1415; +} + - (SEL)methodReturningSEL { return @selector(foo:with:with:); } ++ (BOOL)testMethodReturningSEL:(TestMethod *)o +{ + return [o methodReturningSEL] == @selector(foo:with:with:); +} + - (SEL)methodReturningSEL2 { return 0; } ++ (BOOL)testMethodReturningSEL2:(TestMethod *)o +{ + return [o methodReturningSEL2] == NULL; +} + - (const char *)methodReturningCharPtr { return "foo"; } ++ (BOOL)testMethodReturningCharPtr:(TestMethod *)o +{ + return strcmp([o methodReturningCharPtr], "foo") == 0; +} + - (const char *)methodReturningCharPtr2 { return NULL; } ++ (BOOL)testMethodReturningCharPtr2:(TestMethod *)o +{ + return [o methodReturningCharPtr2] == NULL; +} + - (NSPoint)methodReturningNSPoint { return NSMakePoint(1, 2); } ++ (BOOL)testMethodReturningNSPoint:(TestMethod *)o +{ + return NSEqualPoints([o methodReturningNSPoint], NSMakePoint(1, 2)); +} + - (NSSize)methodReturningNSSize { return NSMakeSize(3, 4); } ++ (BOOL)testMethodReturningNSSize:(TestMethod *)o +{ + return NSEqualSizes([o methodReturningNSSize], NSMakeSize(3, 4)); +} + - (NSRect)methodReturningNSRect { return NSMakeRect(1, 2, 3, 4); } ++ (BOOL)testMethodReturningNSRect:(TestMethod *)o +{ + return NSEqualRects([o methodReturningNSRect], NSMakeRect(1, 2, 3, 4)); +} + - (NSRange)methodReturningNSRange { return NSMakeRange(0, 42); } ++ (BOOL)testMethodReturningNSRange:(TestMethod *)o +{ + return NSEqualRanges([o methodReturningNSRange], NSMakeRange(0, 42)); +} + - (BOOL)methodAcceptingSelf:(id)obj { return obj == self; Modified: MacRuby/branches/experimental/spec/macruby/fixtures/method.rb =================================================================== --- MacRuby/branches/experimental/spec/macruby/fixtures/method.rb 2009-05-02 20:07:25 UTC (rev 1516) +++ MacRuby/branches/experimental/spec/macruby/fixtures/method.rb 2009-05-03 01:02:45 UTC (rev 1517) @@ -18,4 +18,14 @@ def methodReturningLong; 42; end def methodReturningLong2; -42; end def methodReturningUnsignedLong; 42; end + def methodReturningFloat; 3.1415; end + def methodReturningDouble; 3.1415; end + def methodReturningSEL; :'foo:with:with:'; end + def methodReturningSEL2; nil; end + def methodReturningCharPtr; 'foo'; end + def methodReturningCharPtr2; nil; end + def methodReturningNSPoint; NSPoint.new(1, 2); end + def methodReturningNSSize; NSSize.new(3, 4); end + def methodReturningNSRect; NSRect.new(NSPoint.new(1, 2), NSSize.new(3, 4)); end + def methodReturningNSRange; NSRange.new(0, 42); end end Modified: MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb =================================================================== --- MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb 2009-05-02 20:07:25 UTC (rev 1516) +++ MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb 2009-05-03 01:02:45 UTC (rev 1517) @@ -475,4 +475,45 @@ TestMethodOverride.testMethodReturningLong2(@o).should == 1 TestMethodOverride.testMethodReturningUnsignedLong(@o).should == 1 end + + it "can overwrite an Objective-C method returning 'float' or 'double'" do + @o.methodReturningFloat.should == 3.1415 + @o.methodReturningDouble.should == 3.1415 + TestMethodOverride.testMethodReturningFloat(@o).should == 1 + TestMethodOverride.testMethodReturningDouble(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'SEL'" do + @o.methodReturningSEL.should == :'foo:with:with:' + @o.methodReturningSEL2.should == nil + TestMethodOverride.testMethodReturningSEL(@o).should == 1 + TestMethodOverride.testMethodReturningSEL2(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'char *'" do + @o.methodReturningCharPtr.should == 'foo' + @o.methodReturningCharPtr2.should == nil + TestMethodOverride.testMethodReturningCharPtr(@o).should == 1 + TestMethodOverride.testMethodReturningCharPtr2(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'NSPoint'" do + @o.methodReturningNSPoint.should == NSPoint.new(1, 2) + TestMethodOverride.testMethodReturningNSPoint(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'NSSize'" do + @o.methodReturningNSSize.should == NSSize.new(3, 4) + TestMethodOverride.testMethodReturningNSSize(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'NSRect'" do + @o.methodReturningNSRect.should == NSRect.new(NSPoint.new(1, 2), NSSize.new(3, 4)) + TestMethodOverride.testMethodReturningNSRect(@o).should == 1 + end + + it "can overwrite an Objective-C method returning 'NSRange'" do + @o.methodReturningNSRange.should == NSRange.new(0, 42) + TestMethodOverride.testMethodReturningNSRange(@o).should == 1 + end end