aleksandr.urakov created this revision.
aleksandr.urakov added reviewers: zturner, labath, lemo, stella.stamenova.
aleksandr.urakov added a project: LLDB.
Herald added subscribers: lldb-commits, teemperor, abidh.

This patch adds the basic support of methods reconstruction by native PDB 
plugin. It contains only most obvious changes (it processes `LF_ONEMETHOD` and 
`LF_METHOD` records), some things still remain unsolved:

- mangled names retrieving;
- support of template methods (they are not presented as `LF_ONEMETHOD` records 
at all).

This info is contained in the `Symbols` stream, not in the `TPI` stream. As far 
as I understand, we can't find in a simple way the link between a 
`LF_ONEMETHOD` record and a corresponding `S_GPROC32` record. I think it's the 
place, where we need to use the approach similar to D54053 
<https://reviews.llvm.org/D54053> (to parse mangled names and to build some 
part of AST based on this info). That's what I'm planning to implement next. Do 
you have any objections on this? Or may be there's a better way to solve this?


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D56126

Files:
  lit/SymbolFile/NativePDB/Inputs/ast-methods.lldbinit
  lit/SymbolFile/NativePDB/ast-methods.cpp
  source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
  source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
  source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h

Index: source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
+++ source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
@@ -67,6 +67,10 @@
 private:
   clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti,
                                            llvm::codeview::MemberAccess access);
+  void AddMethod(llvm::StringRef name, llvm::codeview::TypeIndex type_idx,
+                 llvm::codeview::MemberAccess access,
+                 llvm::codeview::MethodOptions options,
+                 llvm::codeview::MemberAttributes attrs);
 };
 
 } // namespace npdb
Index: source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
===================================================================
--- source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -65,6 +65,22 @@
   return qt;
 }
 
+void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
+                                   MemberAccess access, MethodOptions options,
+                                   MemberAttributes attrs) {
+  clang::QualType method_qt =
+      m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
+  m_ast_builder.CompleteType(method_qt);
+
+  lldb::AccessType access_type = TranslateMemberAccess(access);
+  bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
+                       MethodOptions::CompilerGenerated;
+  m_ast_builder.clang().AddMethodToCXXRecordType(
+      m_derived_ct.GetOpaqueQualType(), name.data(), nullptr,
+      m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(),
+      attrs.isStatic(), false, false, false, is_artificial);
+}
+
 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
                                            BaseClassRecord &base) {
   clang::QualType base_qt =
@@ -158,11 +174,27 @@
 
 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
                                            OneMethodRecord &one_method) {
+  AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
+            one_method.getOptions(), one_method.Attrs);
+
   return Error::success();
 }
 
 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
                                            OverloadedMethodRecord &overloaded) {
+  TypeIndex method_list_idx = overloaded.MethodList;
+
+  CVType method_list_type = m_tpi.getType(method_list_idx);
+  assert(method_list_type.Type == LF_METHODLIST);
+
+  MethodOverloadListRecord method_list;
+  llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
+      method_list_type, method_list));
+
+  for (const OneMethodRecord &method : method_list.Methods)
+    AddMethod(overloaded.Name, method.Type, method.getAccess(),
+              method.getOptions(), method.Attrs);
+
   return Error::success();
 }
 
Index: source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -100,7 +100,8 @@
   clang::QualType CreateEnumType(PdbTypeSymId id,
                                  const llvm::codeview::EnumRecord &record);
   clang::QualType
-  CreateProcedureType(const llvm::codeview::ProcedureRecord &proc);
+  CreateFunctionType(TypeIndex args_type_idx, TypeIndex return_type_idx,
+                     llvm::codeview::CallingConvention calling_convention);
   clang::QualType CreateType(PdbTypeSymId type);
 
   void CreateFunctionParameters(PdbCompilandSymId func_id,
Index: source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -662,7 +662,14 @@
   if (cvt.kind() == LF_PROCEDURE) {
     ProcedureRecord pr;
     llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
-    return CreateProcedureType(pr);
+    return CreateFunctionType(pr.ArgumentList, pr.ReturnType, pr.CallConv);
+  }
+
+  if (cvt.kind() == LF_MFUNCTION) {
+    MemberFunctionRecord mfr;
+    llvm::cantFail(
+        TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
+    return CreateFunctionType(mfr.ArgumentList, mfr.ReturnType, mfr.CallConv);
   }
 
   return {};
@@ -830,10 +837,11 @@
   return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());
 }
 
-clang::QualType
-PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) {
+clang::QualType PdbAstBuilder::CreateFunctionType(
+    TypeIndex args_type_idx, TypeIndex return_type_idx,
+    llvm::codeview::CallingConvention calling_convention) {
   TpiStream &stream = m_index.tpi();
-  CVType args_cvt = stream.getType(proc.ArgumentList);
+  CVType args_cvt = stream.getType(args_type_idx);
   ArgListRecord args;
   llvm::cantFail(
       TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
@@ -851,10 +859,10 @@
     arg_types.push_back(ToCompilerType(arg_type));
   }
 
-  clang::QualType return_type = GetOrCreateType(proc.ReturnType);
+  clang::QualType return_type = GetOrCreateType(return_type_idx);
 
   llvm::Optional<clang::CallingConv> cc =
-      TranslateCallingConvention(proc.CallConv);
+      TranslateCallingConvention(calling_convention);
   if (!cc)
     return {};
 
Index: lit/SymbolFile/NativePDB/ast-methods.cpp
===================================================================
--- /dev/null
+++ lit/SymbolFile/NativePDB/ast-methods.cpp
@@ -0,0 +1,37 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN:     %p/Inputs/ast-methods.lldbinit 2>&1 | FileCheck %s
+
+struct Struct {
+  void simple_method() {}
+
+  virtual void virtual_method() {}
+
+  static void static_method() {}
+
+  int overloaded_method() {}
+  int overloaded_method(char c) {}
+  int overloaded_method(char c, int i, ...) {}
+};
+
+Struct s;
+
+int main(int argc, char **argv) {
+  return 0;
+}
+
+// CHECK: TranslationUnitDecl
+// CHECK: |-CXXRecordDecl {{.*}} struct Struct definition
+// CHECK: | |-CXXMethodDecl {{.*}} simple_method 'void () __attribute__((thiscall))'
+// CHECK: | |-CXXMethodDecl {{.*}} virtual_method 'void () __attribute__((thiscall))' virtual
+// CHECK: | |-CXXMethodDecl {{.*}} static_method 'void ()' static
+// CHECK: | |-CXXMethodDecl {{.*}} overloaded_method 'int () __attribute__((thiscall))'
+// CHECK: | |-CXXMethodDecl {{.*}} overloaded_method 'int (char) __attribute__((thiscall))'
+// CHECK: | | `-ParmVarDecl {{.*}} 'char'
+// CHECK: | `-CXXMethodDecl {{.*}} overloaded_method 'int (char, int, ...)'
+// CHECK: |   |-ParmVarDecl {{.*}} 'char'
+// CHECK: |   `-ParmVarDecl {{.*}} 'int'
+// CHECK: `-<undeserialized declarations>
Index: lit/SymbolFile/NativePDB/Inputs/ast-methods.lldbinit
===================================================================
--- /dev/null
+++ lit/SymbolFile/NativePDB/Inputs/ast-methods.lldbinit
@@ -0,0 +1,5 @@
+target variable s
+
+target modules dump ast
+
+quit
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to