[Lldb-commits] [lldb] r328389 - Add support for __attribute__(trivial_abi).

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 23 16:44:52 PDT 2018


Author: jingham
Date: Fri Mar 23 16:44:52 2018
New Revision: 328389

URL: http://llvm.org/viewvc/llvm-project?rev=328389&view=rev
Log:
Add support for __attribute__(trivial_abi).

<rdar://problem/36035075>, <rdar://problem/36035039>

Added:
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/TestTrivialABI.py
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/main.cpp
Modified:
    lldb/trunk/packages/Python/lldbsuite/test/decorators.py
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/decorators.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/decorators.py?rev=328389&r1=328388&r2=328389&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/decorators.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/decorators.py Fri Mar 23 16:44:52 2018
@@ -652,6 +652,19 @@ def skipIfTargetAndroid(api_levels=None,
             api_levels,
             archs))
 
+def skipUnlessSupportedTypeAttribute(attr):
+    """Decorate the item to skip test unless Clang supports type __attribute__(attr)."""
+    def compiler_doesnt_support_struct_attribute(self):
+        compiler_path = self.getCompiler()
+        compiler = os.path.basename(compiler_path)
+        f = tempfile.NamedTemporaryFile()
+        cmd = "echo 'struct __attribute__((%s)) Test {};' | %s -x c++ -c -o %s - ; exit" % (attr, compiler_path, f.name)
+        p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
+        test_result = p.stderr.read()
+        if attr in test_result:
+            return "Compiler does not support attribute %s"%(attr)
+        return None
+    return skipTestIfFn(compiler_doesnt_support_struct_attribute)
 
 def skipUnlessThreadSanitizer(func):
     """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/Makefile?rev=328389&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/Makefile Fri Mar 23 16:44:52 2018
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/TestTrivialABI.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/TestTrivialABI.py?rev=328389&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/TestTrivialABI.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/TestTrivialABI.py Fri Mar 23 16:44:52 2018
@@ -0,0 +1,75 @@
+"""
+Test that we work properly with classes with the trivial_abi attribute
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import decorators
+
+class TestTrivialABI(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @decorators.skipUnlessSupportedTypeAttribute("trivial_abi")
+    def test_call_trivial(self):
+        """Test that we can print a variable & call a function with a trivial ABI class."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("main.cpp")
+        self.expr_test(True)
+
+    @decorators.skipUnlessSupportedTypeAttribute("trivial_abi")
+    @decorators.expectedFailureAll(bugnumber="llvm.org/pr36870")
+    def test_call_nontrivial(self):
+        """Test that we can print a variable & call a function on the same class w/o the trivial ABI marker."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("main.cpp")
+        self.expr_test(False)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+
+    def check_value(self, test_var, ivar_value):
+        self.assertTrue(test_var.GetError().Success(), "Invalid valobj: %s"%(test_var.GetError().GetCString()))
+        ivar = test_var.GetChildMemberWithName("ivar")
+        self.assertTrue(test_var.GetError().Success(), "Failed to fetch ivar")
+        self.assertEqual(ivar_value, ivar.GetValueAsSigned(), "Got the right value for ivar")
+        
+    def check_frame(self, thread):
+        frame = thread.frames[0]
+        inVal_var = frame.FindVariable("inVal")
+        self.check_value(inVal_var, 10)
+
+        options = lldb.SBExpressionOptions()
+        inVal_expr = frame.EvaluateExpression("inVal", options)
+        self.check_value(inVal_expr, 10)
+        
+        thread.StepOut()
+        outVal_ret = thread.GetStopReturnValue()
+        self.check_value(outVal_ret, 30)
+        
+    def expr_test(self, trivial):
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+                                   "Set a breakpoint here", self.main_source_file) 
+
+        # Stop in a function that takes a trivial value, and try both frame var & expr to get its value:
+        if trivial:
+            self.check_frame(thread)
+            return
+
+        # Now continue to the same thing without the trivial_abi and see if we get that right:
+        threads = lldbutil.continue_to_breakpoint(process, bkpt)
+        self.assertEqual(len(threads), 1, "Hit my breakpoint the second time.")
+
+        self.check_frame(threads[0])
+        
+

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/main.cpp?rev=328389&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/trivial_abi/main.cpp Fri Mar 23 16:44:52 2018
@@ -0,0 +1,35 @@
+struct __attribute__((trivial_abi)) S_Trivial {
+  ~S_Trivial() {}
+  int ivar = 10;
+};
+
+S_Trivial takeTrivial(S_Trivial inVal)
+{
+  S_Trivial ret_val = inVal;
+  ret_val.ivar = 30;
+  return ret_val;   // Set a breakpoint here
+}
+
+struct S_NotTrivial {
+  ~S_NotTrivial() {}
+  int ivar = 10;
+};
+
+S_NotTrivial takeNotTrivial(S_NotTrivial inVal)
+{
+  S_NotTrivial ret_val = inVal;
+  ret_val.ivar = 30;
+  return ret_val;   // Set a breakpoint here
+}
+
+int
+main()
+{
+  S_Trivial inVal, outVal;
+  outVal = takeTrivial(inVal);
+
+  S_NotTrivial inNotVal, outNotVal;
+  outNotVal = takeNotTrivial(outNotVal);
+
+  return 0; // Set another for return value
+}

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=328389&r1=328388&r2=328389&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Fri Mar 23 16:44:52 2018
@@ -573,6 +573,9 @@ TypeSP DWARFASTParserClang::ParseTypeFro
 
         LanguageType class_language = eLanguageTypeUnknown;
         bool is_complete_objc_class = false;
+        size_t calling_convention 
+                = llvm::dwarf::CallingConvention::DW_CC_normal;
+        
         // bool struct_is_class = false;
         const size_t num_attributes = die.GetAttributes(attributes);
         if (num_attributes > 0) {
@@ -628,7 +631,10 @@ TypeSP DWARFASTParserClang::ParseTypeFro
               case DW_AT_APPLE_objc_complete_type:
                 is_complete_objc_class = form_value.Signed();
                 break;
-
+              case DW_AT_calling_convention:
+                calling_convention = form_value.Unsigned();
+                break;
+                
               case DW_AT_allocated:
               case DW_AT_associated:
               case DW_AT_data_location:
@@ -884,7 +890,7 @@ TypeSP DWARFASTParserClang::ParseTypeFro
                                                 class_language, &metadata);
           }
         }
-
+        
         // Store a forward declaration to this class type in case any
         // parameters in any class methods need it for the clang
         // types for function prototypes.
@@ -997,6 +1003,20 @@ TypeSP DWARFASTParserClang::ParseTypeFro
             m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
           }
         }
+        
+        // If we made a clang type, set the trivial abi if applicable:
+        // We only do this for pass by value - which implies the Trivial ABI.
+        // There isn't a way to assert that something that would normally be
+        // pass by value is pass by reference, so we ignore that attribute if
+        // set.
+        if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
+          clang::CXXRecordDecl *record_decl =
+                  m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+          if (record_decl) {
+            record_decl->setHasTrivialSpecialMemberForCall();
+          }
+        }
+
       } break;
 
       case DW_TAG_enumeration_type: {




More information about the lldb-commits mailing list