From b12ac2b6891724c5cab708466cbad956ea2316e2 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Wed, 27 Feb 2019 20:27:25 +0000 Subject: [PATCH] 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. Differential Revision: https://reviews.llvm.org/D58699 llvm-svn: 355026 --- .../lang/objc/objc-checker/TestObjCCheckers.py | 15 +++++++++++++++ .../lldbsuite/test/lang/objc/objc-checker/main.m | 15 +++++++++++++++ lldb/source/Expression/IRDynamicChecks.cpp | 11 +++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py index 644cd87305e9..7c3bafaeb4e8 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py +++ b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py @@ -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()) + diff --git a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m index 4a09a2826f70..de73e688f25c 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m +++ b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m @@ -1,11 +1,19 @@ #import +// 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 () diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp index 4bc7cc83ca4c..854aca335d2a 100644 --- a/lldb/source/Expression/IRDynamicChecks.cpp +++ b/lldb/source/Expression/IRDynamicChecks.cpp @@ -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);