[Lldb-commits] [lldb] r236297 - Added support for locating and importing functions

Sean Callanan scallanan at apple.com
Thu Apr 30 17:47:30 PDT 2015


Author: spyffe
Date: Thu Apr 30 19:47:29 2015
New Revision: 236297

URL: http://llvm.org/viewvc/llvm-project?rev=236297&view=rev
Log:
Added support for locating and importing functions
(including inline functions) from modules in the
expression parser.  We now have to retain a reference
to the code generator in ClangExpressionDeclMap so
that any imported function bodies can be appropriately
sent to that code generator.

<rdar://problem/19883002>

Added:
    lldb/trunk/test/lang/objc/modules-inline-functions/
    lldb/trunk/test/lang/objc/modules-inline-functions/Makefile
    lldb/trunk/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
    lldb/trunk/test/lang/objc/modules-inline-functions/main.m
    lldb/trunk/test/lang/objc/modules-inline-functions/module.map
    lldb/trunk/test/lang/objc/modules-inline-functions/myModule.c
    lldb/trunk/test/lang/objc/modules-inline-functions/myModule.h
Modified:
    lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Expression/ClangExpressionParser.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=236297&r1=236296&r2=236297&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Thu Apr 30 19:47:29 2015
@@ -100,6 +100,9 @@ public:
     WillParse (ExecutionContext &exe_ctx,
                Materializer *materializer);
     
+    void
+    InstallCodeGenerator (clang::ASTConsumer *code_gen);
+    
     //------------------------------------------------------------------
     /// [Used by ClangExpressionParser] For each variable that had an unknown
     ///     type at the beginning of parsing, determine its final type now.
@@ -396,11 +399,6 @@ private:
     {
     public:
         ParserVars(ClangExpressionDeclMap &decl_map) :
-            m_exe_ctx(),
-            m_sym_ctx(),
-            m_persistent_vars(NULL),
-            m_enable_lookups(false),
-            m_materializer(NULL),
             m_decl_map(decl_map)
         {
         }
@@ -415,12 +413,13 @@ private:
             return NULL;
         }
         
-        ExecutionContext            m_exe_ctx;          ///< The execution context to use when parsing.
-        SymbolContext               m_sym_ctx;          ///< The symbol context to use in finding variables and types.
-        ClangPersistentVariables   *m_persistent_vars;  ///< The persistent variables for the process.
-        bool                        m_enable_lookups;   ///< Set to true during parsing if we have found the first "$__lldb" name.
-        TargetInfo                  m_target_info;      ///< Basic information about the target.
-        Materializer               *m_materializer;     ///< If non-NULL, the materializer to use when reporting used variables.
+        ExecutionContext            m_exe_ctx;                      ///< The execution context to use when parsing.
+        SymbolContext               m_sym_ctx;                      ///< The symbol context to use in finding variables and types.
+        ClangPersistentVariables   *m_persistent_vars = nullptr;    ///< The persistent variables for the process.
+        bool                        m_enable_lookups = false;       ///< Set to true during parsing if we have found the first "$__lldb" name.
+        TargetInfo                  m_target_info;                  ///< Basic information about the target.
+        Materializer               *m_materializer = nullptr;       ///< If non-NULL, the materializer to use when reporting used variables.
+        clang::ASTConsumer         *m_code_gen = nullptr;           ///< If non-NULL, a code generator that receives new top-level functions.
     private:
         ClangExpressionDeclMap     &m_decl_map;
         DISALLOW_COPY_AND_ASSIGN (ParserVars);

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=236297&r1=236296&r2=236297&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Apr 30 19:47:29 2015
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Decl.h"
@@ -111,6 +112,13 @@ ClangExpressionDeclMap::WillParse(Execut
 }
 
 void
+ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen)
+{
+    assert(m_parser_vars);
+    m_parser_vars->m_code_gen = code_gen;
+}
+
+void
 ClangExpressionDeclMap::DidParse()
 {
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1487,6 +1495,62 @@ ClangExpressionDeclMap::FindExternalVisi
                     }
                 }
             }
+            
+            if (!context.m_found.function_with_type_info)
+            {
+                // Try the modules next.
+                
+                do
+                {
+                    if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
+                    {
+                        bool append = false;
+                        uint32_t max_matches = 1;
+                        std::vector <clang::NamedDecl *> decls;
+                        
+                        if (!modules_decl_vendor->FindDecls(name,
+                                                            append,
+                                                            max_matches,
+                                                            decls))
+                            break;
+                        
+                        clang::NamedDecl *const decl_from_modules = decls[0];
+                        
+                        if (llvm::isa<clang::FunctionDecl>(decl_from_modules))
+                        {
+                            if (log)
+                            {
+                                log->Printf("  CAS::FEVD[%u] Matching function found for \"%s\" in the modules",
+                                            current_id,
+                                            name.GetCString());
+                            }
+                            
+                            clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+                            clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr;
+                            
+                            if (!copied_function_decl)
+                            {
+                                if (log)
+                                    log->Printf("  CAS::FEVD[%u] - Couldn't export a function declaration from the modules",
+                                                current_id);
+                                
+                                break;
+                            }
+                            
+                            if (copied_function_decl->getBody() && m_parser_vars->m_code_gen)
+                            {
+                                DeclGroupRef decl_group_ref(copied_function_decl);
+                                m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
+                            }
+                            
+                            context.AddNamedDecl(copied_function_decl);
+                            
+                            context.m_found.function_with_type_info = true;
+                            context.m_found.function = true;
+                        }
+                    }
+                } while (0);
+            }
 
             if (target && !context.m_found.variable && !namespace_decl)
             {

Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=236297&r1=236296&r2=236297&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Thu Apr 30 19:47:29 2015
@@ -409,6 +409,9 @@ ClangExpressionParser::Parse (Stream &st
 
     ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
 
+    if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap())
+        decl_map->InstallCodeGenerator(m_code_generator.get());
+    
     if (ast_transformer)
         ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
     else

Added: lldb/trunk/test/lang/objc/modules-inline-functions/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/Makefile?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/Makefile (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/Makefile Thu Apr 30 19:47:29 2015
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+C_SOURCES := myModule.c
+
+OBJC_SOURCES := main.m
+
+include $(LEVEL)/Makefile.rules
+
+CFLAGS += -fmodules -I$(PWD)

Added: lldb/trunk/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py Thu Apr 30 19:47:29 2015
@@ -0,0 +1,80 @@
+"""Test that inline functions from modules are imported correctly"""
+
+import os, time
+import unittest2
+import lldb
+import platform
+import lldbutil
+
+from distutils.version import StrictVersion
+
+from lldbtest import *
+
+class ModulesInlineFunctionsTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipUnlessDarwin
+    @dsym_test
+    def test_expr_with_dsym(self):
+        self.buildDsym()
+        self.expr()
+
+    @dwarf_test
+    @skipIfFreeBSD
+    @skipIfLinux
+    def test_expr_with_dwarf(self):
+        self.buildDwarf()
+        self.expr()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to break inside main().
+        self.line = line_number('main.m', '// Set breakpoint here.')
+
+    def applies(self):
+        if platform.system() != "Darwin":
+            return False
+        if StrictVersion('12.0.0') > platform.release():
+            return False
+
+        return True
+
+    def common_setup(self):
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Break inside the foo function which takes a bar_ptr argument.
+        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # The breakpoint should have a hit count of 1.
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+            substrs = [' resolved, hit count = 1'])
+
+    def expr(self):
+        if not self.applies():
+            return
+
+        self.common_setup()
+
+        self.runCmd("settings set target.clang-module-search-paths \"" + os.getcwd() + "\"")
+
+        self.expect("expr @import myModule; 3", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ["int", "3"])
+
+        self.expect("expr isInline(2)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ["4"])
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/objc/modules-inline-functions/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/main.m?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/main.m (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/main.m Thu Apr 30 19:47:29 2015
@@ -0,0 +1,9 @@
+ at import Darwin;
+ at import myModule;
+
+int main()
+{
+    int a = isInline(2);
+    int b = notInline();
+    printf("%d %d\n", a, b); // Set breakpoint here.
+}

Added: lldb/trunk/test/lang/objc/modules-inline-functions/module.map
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/module.map?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/module.map (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/module.map Thu Apr 30 19:47:29 2015
@@ -0,0 +1,4 @@
+module myModule {
+  header "myModule.h"
+  export *
+}

Added: lldb/trunk/test/lang/objc/modules-inline-functions/myModule.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/myModule.c?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/myModule.c (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/myModule.c Thu Apr 30 19:47:29 2015
@@ -0,0 +1,7 @@
+#include "myModule.h"
+
+int notInline()
+{
+    return 3;
+}
+

Added: lldb/trunk/test/lang/objc/modules-inline-functions/myModule.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/modules-inline-functions/myModule.h?rev=236297&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/modules-inline-functions/myModule.h (added)
+++ lldb/trunk/test/lang/objc/modules-inline-functions/myModule.h Thu Apr 30 19:47:29 2015
@@ -0,0 +1,7 @@
+int notInline();
+
+static __inline__ __attribute__ ((always_inline)) int isInline(int a)
+{
+    int b = a + a;
+    return b;
+}





More information about the lldb-commits mailing list