Pass arguments correctly to the objc object checker on arm64
Traditionally objc had two entry points, objc_msgSend for scalar return methods, and objc_msgSend_stret for struct return convention methods. But on arm64 the second was not needed (since arm64 doesn't use an argument register for the struct return pointer) so it was removed. The code that dispatches to the objc object checker when it sees some flavor of objc_msgSend was not aware of this change so was sending the wrong arguments to the checker. <rdar://problem/48315890> Differential Revision: https://reviews.llvm.org/D58699 llvm-svn: 355026
This commit is contained in:
parent
288a95fc8c
commit
b12ac2b689
|
@ -18,6 +18,8 @@ class ObjCCheckerTestCase(TestBase):
|
|||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
@ -77,3 +79,16 @@ class ObjCCheckerTestCase(TestBase):
|
|||
# Make sure the error is helpful:
|
||||
err_string = expr_error.GetCString()
|
||||
self.assertTrue("selector" in err_string)
|
||||
|
||||
#
|
||||
# Check that we correctly insert the checker for an
|
||||
# ObjC method with the struct return convention.
|
||||
# Getting this wrong would cause us to call the checker
|
||||
# with the wrong arguments, and the checker would crash
|
||||
# So I'm just checking "expression runs successfully" here:
|
||||
#
|
||||
expr_value = frame.EvaluateExpression("[my_simple getBigStruct]", False)
|
||||
expr_error = expr_value.GetError()
|
||||
|
||||
self.assertTrue(expr_error.Success())
|
||||
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
// This should be a big enough struct that it will force
|
||||
// the struct return convention:
|
||||
typedef struct BigStruct {
|
||||
float a, b, c, d, e, f, g, h, i, j, k, l;
|
||||
} BigStruct;
|
||||
|
||||
|
||||
@interface Simple : NSObject
|
||||
{
|
||||
int _value;
|
||||
}
|
||||
- (int) value;
|
||||
- (void) setValue: (int) newValue;
|
||||
- (BigStruct) getBigStruct;
|
||||
@end
|
||||
|
||||
@implementation Simple
|
||||
|
@ -18,6 +26,13 @@
|
|||
{
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
- (BigStruct) getBigStruct
|
||||
{
|
||||
BigStruct big_struct = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
|
||||
7.0, 8.0, 9.0, 10.0, 11.0, 12.0};
|
||||
return big_struct;
|
||||
}
|
||||
@end
|
||||
|
||||
int main ()
|
||||
|
|
|
@ -424,8 +424,15 @@ protected:
|
|||
switch (msgSend_types[inst]) {
|
||||
case eMsgSend:
|
||||
case eMsgSend_fpret:
|
||||
target_object = call_inst->getArgOperand(0);
|
||||
selector = call_inst->getArgOperand(1);
|
||||
// On arm64, clang uses objc_msgSend for scalar and struct return
|
||||
// calls. The call instruction will record which was used.
|
||||
if (call_inst->hasStructRetAttr()) {
|
||||
target_object = call_inst->getArgOperand(1);
|
||||
selector = call_inst->getArgOperand(2);
|
||||
} else {
|
||||
target_object = call_inst->getArgOperand(0);
|
||||
selector = call_inst->getArgOperand(1);
|
||||
}
|
||||
break;
|
||||
case eMsgSend_stret:
|
||||
target_object = call_inst->getArgOperand(1);
|
||||
|
|
Loading…
Reference in New Issue