teemperor created this revision. teemperor added reviewers: aprantl, shafik. Herald added subscribers: lldb-commits, JDevlieghere. Herald added a project: LLDB.
D69991 <https://reviews.llvm.org/D69991> introduced `__attribute__((objc_direct))` that allows directly calling methods without message passing. This patch adds support for calling methods with this attribute to LLDB's expression evaluator. The patch can be summarised in that LLDB just adds the same attribute to our module AST when we find a method with `__attribute__((objc_direct))` in our debug information. Repository: rLLDB LLDB https://reviews.llvm.org/D71196 Files: lldb/include/lldb/Symbol/ClangASTContext.h lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/Makefile lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/TestObjCDirectMethods.py lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/main.m lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h lldb/source/Symbol/ClangASTContext.cpp
Index: lldb/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/source/Symbol/ClangASTContext.cpp +++ lldb/source/Symbol/ClangASTContext.cpp @@ -8485,7 +8485,7 @@ // (lldb::opaque_compiler_type_t type, "-[NString // stringWithCString:]") const CompilerType &method_clang_type, lldb::AccessType access, - bool is_artificial, bool is_variadic) { + bool is_artificial, bool is_variadic, bool is_objc_direct_call) { if (!type || !method_clang_type.IsValid()) return nullptr; @@ -8591,6 +8591,18 @@ llvm::ArrayRef<clang::SourceLocation>()); } + if (is_objc_direct_call) { + // Add a the objc_direct attribute to the declaration we generate that + // we generate a direct method call for this ObjCMethodDecl. + objc_method_decl->addAttr( + clang::ObjCDirectAttr::CreateImplicit(*ast, SourceLocation())); + // Usually Sema is creating implicit parameters (e.g., self) when it + // parses the method. We don't have a parsing Sema when we build our own + // AST here so we manually need to create these implicit parameters to + // make the direct call code generation happy. + objc_method_decl->createImplicitParams(*ast, class_interface_decl); + } + class_interface_decl->addDecl(objc_method_decl); #ifdef LLDB_CONFIGURATION_DEBUG Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -244,6 +244,7 @@ bool is_scoped_enum = false; bool is_vector = false; bool is_virtual = false; + bool is_objc_direct_call = false; bool exports_symbols = false; clang::StorageClass storage = clang::SC_None; const char *mangled_name = nullptr; Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -390,6 +390,10 @@ is_complete_objc_class = form_value.Signed(); break; + case DW_AT_APPLE_objc_direct: + is_objc_direct_call = true; + break; + case DW_AT_APPLE_runtime_class: class_language = (LanguageType)form_value.Signed(); break; @@ -954,7 +958,8 @@ clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType( class_opaque_type, attrs.name.GetCString(), clang_type, - attrs.accessibility, attrs.is_artificial, is_variadic); + attrs.accessibility, attrs.is_artificial, is_variadic, + attrs.is_objc_direct_call); type_handled = objc_method_decl != NULL; if (type_handled) { LinkDeclContextToDIE(objc_method_decl, die); Index: lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/main.m =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/main.m @@ -0,0 +1,79 @@ +#import <Foundation/Foundation.h> + +int side_effect = 0; + +NSString *str = @"some string"; + +const char *directCallConflictingName() { + return "wrong function"; +} + +@interface Foo : NSObject { + int instance_var; +} +-(int) entryPoint; +@end + +@implementation Foo +-(int) entryPoint +{ + // Try calling directly with self. Same as in the main method otherwise. + return 0; //%self.expect("expr [self directCallNoArgs]", substrs=["called directCallNoArgs"]) + //%self.expect("expr [self directCallArgs: 1111]", substrs=["= 2345"]) + //%self.expect("expr side_effect = 0; [self directCallVoidReturn]; side_effect", substrs=["= 4321"]) + //%self.expect("expr [self directCallNSStringArg: str]", substrs=['@"some string"']) + //%self.expect("expr [self directCallIdArg: (id)str]", substrs=['@"some string appendix"']) + //%self.expect("expr [self directCallConflictingName]", substrs=["correct function"]) +} + +// Declare several objc_direct functions we can test. +-(const char *) directCallNoArgs __attribute__((objc_direct)) +{ + return "called directCallNoArgs"; +} + +-(void) directCallVoidReturn __attribute__((objc_direct)) +{ + side_effect = 4321; +} + +-(int) directCallArgs:(int)i __attribute__((objc_direct)) +{ + // Use the arg in some way to make sure that gets passed correctly. + return i + 1234; +} + +-(NSString *) directCallNSStringArg:(NSString *)str __attribute__((objc_direct)) +{ + return str; +} + +-(NSString *) directCallIdArg:(id)param __attribute__((objc_direct)) +{ + return [param stringByAppendingString:@" appendix"]; +} + +// We have another function with the same name above. Make sure this doesn't influence +// what we call. +-(const char *) directCallConflictingName __attribute__((objc_direct)) +{ + return "correct function"; +} +@end + +int main() +{ + Foo *foo = [[Foo alloc] init]; + [foo directCallNoArgs]; + [foo directCallArgs: 1]; + [foo directCallVoidReturn]; + [foo directCallNSStringArg: str]; + [foo directCallIdArg: (id)str]; + [foo entryPoint]; //%self.expect("expr [foo directCallNoArgs]", substrs=["called directCallNoArgs"]) + //%self.expect("expr [foo directCallArgs: 1111]", substrs=["= 2345"]) + //%self.expect("expr side_effect = 0; [foo directCallVoidReturn]; side_effect", substrs=["= 4321"]) + //%self.expect("expr [foo directCallNSStringArg: str]", substrs=['@"some string"']) + //%self.expect("expr [foo directCallIdArg: (id)str]", substrs=['@"some string appendix"']) + //%self.expect("expr [foo directCallConflictingName]", substrs=["correct function"]) + return 0; +} Index: lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/TestObjCDirectMethods.py =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/TestObjCDirectMethods.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [decorators.skipUnlessDarwin]) Index: lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/Makefile =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/objc/objc_direct-methods/Makefile @@ -0,0 +1,4 @@ +OBJC_SOURCES := main.m +LD_EXTRAS := -lobjc -framework Foundation + +include Makefile.rules Index: lldb/include/lldb/Symbol/ClangASTContext.h =================================================================== --- lldb/include/lldb/Symbol/ClangASTContext.h +++ lldb/include/lldb/Symbol/ClangASTContext.h @@ -825,7 +825,7 @@ // (lldb::opaque_compiler_type_t type, "-[NString // stringWithCString:]") const CompilerType &method_compiler_type, lldb::AccessType access, - bool is_artificial, bool is_variadic); + bool is_artificial, bool is_variadic, bool is_objc_direct_call); static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type, bool has_extern);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits