[llvm] r273084 - [codeview] Emit non-virtual method type.

Amjad Aboud via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 18 03:25:08 PDT 2016


Author: aaboud
Date: Sat Jun 18 05:25:07 2016
New Revision: 273084

URL: http://llvm.org/viewvc/llvm-project?rev=273084&view=rev
Log:
[codeview] Emit non-virtual method type.

Differential Revision: http://reviews.llvm.org/D21011

Added:
    llvm/trunk/test/DebugInfo/COFF/types-non-virtual-methods.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/trunk/test/DebugInfo/COFF/types-basic.ll
    llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll
    llvm/trunk/test/DebugInfo/COFF/types-data-members.ll
    llvm/trunk/test/DebugInfo/COFF/types-ptr-to-member.ll

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Sat Jun 18 05:25:07 2016
@@ -24,9 +24,9 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -130,7 +130,7 @@ TypeIndex CodeViewDebug::getFuncIdForSub
     return TypeIndex::None();
 
   // Check if we've already translated this subprogram.
-  auto I = TypeIndices.find(SP);
+  auto I = TypeIndices.find({SP, nullptr});
   if (I != TypeIndices.end())
     return I->second;
 
@@ -138,19 +138,24 @@ TypeIndex CodeViewDebug::getFuncIdForSub
   // The display name includes function template arguments. Drop them to match
   // MSVC.
   StringRef DisplayName = SP->getDisplayName().split('<').first;
-  FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
+  FuncIdRecord FuncId(ParentScope, lowerSubprogramType(SP), DisplayName);
   TypeIndex TI = TypeTable.writeFuncId(FuncId);
 
   recordTypeIndexForDINode(SP, TI);
   return TI;
 }
 
-void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI) {
-  auto InsertResult = TypeIndices.insert({Node, TI});
+void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
+                                             const DIType *ClassTy) {
+  auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
   (void)InsertResult;
   assert(InsertResult.second && "DINode was already assigned a type index");
 }
 
+unsigned CodeViewDebug::getPointerSizeInBytes() {
+  return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
+}
+
 void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
                                         const DILocation *InlinedAt) {
   if (InlinedAt) {
@@ -296,8 +301,7 @@ static void emitNullTerminatedSymbolName
 void CodeViewDebug::emitTypeInformation() {
   // Do nothing if we have no debug info or if no non-trivial types were emitted
   // to TypeTable during codegen.
-  NamedMDNode *CU_Nodes =
-      MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+  NamedMDNode *CU_Nodes = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
   if (!CU_Nodes)
     return;
   if (TypeTable.empty())
@@ -341,7 +345,6 @@ void CodeViewDebug::emitInlineeLinesSubs
   if (InlinedSubprograms.empty())
     return;
 
-
   OS.AddComment("Inlinee lines subsection");
   MCSymbol *InlineEnd = beginCVSubsection(ModuleSubstreamKind::InlineeLines);
 
@@ -351,8 +354,8 @@ void CodeViewDebug::emitInlineeLinesSubs
   OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
 
   for (const DISubprogram *SP : InlinedSubprograms) {
-    assert(TypeIndices.count(SP));
-    TypeIndex InlineeIdx = TypeIndices[SP];
+    assert(TypeIndices.count({SP, nullptr}));
+    TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];
 
     OS.AddBlankLine();
     unsigned FileId = maybeRecordFile(SP->getFile());
@@ -390,8 +393,8 @@ void CodeViewDebug::emitInlinedCallSite(
   MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
            *InlineEnd = MMI->getContext().createTempSymbol();
 
-  assert(TypeIndices.count(Site.Inlinee));
-  TypeIndex InlineeIdx = TypeIndices[Site.Inlinee];
+  assert(TypeIndices.count({Site.Inlinee, nullptr}));
+  TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
 
   // SymbolRecord
   OS.AddComment("Record length");
@@ -770,7 +773,7 @@ void CodeViewDebug::beginFunction(const
   }
 }
 
-TypeIndex CodeViewDebug::lowerType(const DIType *Ty) {
+TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
   // Generic dispatch for lowering an unknown type.
   switch (Ty->getTag()) {
   case dwarf::DW_TAG_array_type:
@@ -789,6 +792,8 @@ TypeIndex CodeViewDebug::lowerType(const
   case dwarf::DW_TAG_volatile_type:
     return lowerTypeModifier(cast<DIDerivedType>(Ty));
   case dwarf::DW_TAG_subroutine_type:
+    if (ClassTy)
+      return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy);
     return lowerTypeFunction(cast<DISubroutineType>(Ty));
   case dwarf::DW_TAG_enumeration_type:
     return lowerTypeEnum(cast<DICompositeType>(Ty));
@@ -945,6 +950,13 @@ TypeIndex CodeViewDebug::lowerTypeBasic(
 TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
   TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
 
+  // While processing the type being pointed to it is possible we already
+  // created this pointer type.  If so, we check here and return the existing
+  // pointer type.
+  auto I = TypeIndices.find({Ty, nullptr});
+  if (I != TypeIndices.end())
+    return I->second;
+
   // Pointers to simple types can use SimpleTypeMode, rather than having a
   // dedicated pointer type record.
   if (PointeeTI.isSimple() &&
@@ -1015,7 +1027,7 @@ translatePtrToMemberRep(unsigned SizeInB
 TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
   assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
   TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
-  TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
+  TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType());
   PointerKind PK = Asm->MAI->getPointerSize() == 8 ? PointerKind::Near64
                                                    : PointerKind::Near32;
   bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
@@ -1065,6 +1077,14 @@ TypeIndex CodeViewDebug::lowerTypeModifi
       BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve();
   }
   TypeIndex ModifiedTI = getTypeIndex(BaseTy);
+
+  // While processing the type being pointed to, it is possible we already
+  // created this modifier type.  If so, we check here and return the existing
+  // modifier type.
+  auto I = TypeIndices.find({Ty, nullptr});
+  if (I != TypeIndices.end())
+    return I->second;
+
   ModifierRecord MR(ModifiedTI, Mods);
   return TypeTable.writeModifier(MR);
 }
@@ -1087,16 +1107,63 @@ TypeIndex CodeViewDebug::lowerTypeFuncti
 
   CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
 
-  // TODO: Some functions are member functions, we should use a more appropriate
-  // record for those.
   ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
                             ArgTypeIndices.size(), ArgListIndex);
   return TypeTable.writeProcedure(Procedure);
 }
 
-static MemberAccess translateAccessFlags(unsigned RecordTag,
-                                         const DIType *Member) {
-  switch (Member->getFlags() & DINode::FlagAccessibility) {
+TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
+                                                 const DIType *ClassTy) {
+  // Lower the containing class type.
+  TypeIndex ClassType = getTypeIndex(ClassTy);
+
+  // While processing the class type it is possible we already created this
+  // member function.  If so, we check here and return the existing one.
+  auto I = TypeIndices.find({Ty, ClassTy});
+  if (I != TypeIndices.end())
+    return I->second;
+
+  SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
+  for (DITypeRef ArgTypeRef : Ty->getTypeArray())
+    ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+
+  TypeIndex ReturnTypeIndex = TypeIndex::Void();
+  ArrayRef<TypeIndex> ArgTypeIndices = None;
+  if (!ReturnAndArgTypeIndices.empty()) {
+    auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
+    ReturnTypeIndex = ReturnAndArgTypesRef.front();
+    ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
+  }
+  TypeIndex ThisTypeIndex = TypeIndex::Void();
+  if (!ArgTypeIndices.empty()) {
+    ThisTypeIndex = ArgTypeIndices.front();
+    ArgTypeIndices = ArgTypeIndices.drop_front();
+  }
+
+  ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
+  TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
+
+  CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
+
+  // TODO: Need to use the correct values for:
+  //       FunctionOptions
+  //       ThisPointerAdjustment.
+  TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
+      ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
+      ArgTypeIndices.size(), ArgListIndex, 0));
+
+  return TI;
+}
+
+TypeIndex CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) {
+  auto ClassType = dyn_cast_or_null<DIType>(SP->getScope().resolve());
+  TypeIndex TI = getTypeIndex(SP->getType(), ClassType);
+
+  return TI;
+}
+
+static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags) {
+  switch (Flags & DINode::FlagAccessibility) {
   case DINode::FlagPrivate:   return MemberAccess::Private;
   case DINode::FlagPublic:    return MemberAccess::Public;
   case DINode::FlagProtected: return MemberAccess::Protected;
@@ -1108,6 +1175,34 @@ static MemberAccess translateAccessFlags
   llvm_unreachable("access flags are exclusive");
 }
 
+static MethodOptions translateMethodOptionFlags(const DISubprogram *SP) {
+  if (SP->isArtificial())
+    return MethodOptions::CompilerGenerated;
+
+  // FIXME: Handle other MethodOptions.
+
+  return MethodOptions::None;
+}
+
+static MethodKind translateMethodKindFlags(const DISubprogram *SP,
+                                           bool Introduced) {
+  switch (SP->getVirtuality()) {
+  case dwarf::DW_VIRTUALITY_none:
+    break;
+  case dwarf::DW_VIRTUALITY_virtual:
+    return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
+  case dwarf::DW_VIRTUALITY_pure_virtual:
+    return Introduced ? MethodKind::PureIntroducingVirtual
+                      : MethodKind::PureVirtual;
+  default:
+    llvm_unreachable("unhandled virtuality case");
+  }
+
+  // FIXME: Get Clang to mark DISubprogram as static and do something with it.
+
+  return MethodKind::Vanilla;
+}
+
 static TypeRecordKind getRecordKind(const DICompositeType *Ty) {
   switch (Ty->getTag()) {
   case dwarf::DW_TAG_class_type:     return TypeRecordKind::Class;
@@ -1153,6 +1248,102 @@ TypeIndex CodeViewDebug::lowerTypeEnum(c
                                         getTypeIndex(Ty->getBaseType())));
 }
 
+//===----------------------------------------------------------------------===//
+// ClassInfo
+//===----------------------------------------------------------------------===//
+
+struct llvm::ClassInfo {
+  struct MemberInfo {
+    const DIDerivedType *MemberTypeNode;
+    unsigned BaseOffset;
+  };
+  // [MemberInfo]
+  typedef std::vector<MemberInfo> MemberList;
+
+  struct MethodInfo {
+    const DISubprogram *Method;
+    bool Introduced;
+  };
+  // [MethodInfo]
+  typedef std::vector<MethodInfo> MethodsList;
+  // MethodName -> MethodsList
+  typedef MapVector<MDString *, MethodsList> MethodsMap;
+
+  /// Direct members.
+  MemberList Members;
+  // Direct overloaded methods gathered by name.
+  MethodsMap Methods;
+};
+
+void CodeViewDebug::clear() {
+  assert(CurFn == nullptr);
+  FileIdMap.clear();
+  FnDebugInfo.clear();
+  FileToFilepathMap.clear();
+  LocalUDTs.clear();
+  GlobalUDTs.clear();
+  TypeIndices.clear();
+  CompleteTypeIndices.clear();
+  ClassInfoMap.clear();
+}
+
+void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
+                                      const DIDerivedType *DDTy) {
+  if (!DDTy->getName().empty()) {
+    Info.Members.push_back({DDTy, 0});
+    return;
+  }
+  // Member with no name, must be nested structure/union, collects its memebers
+  assert((DDTy->getOffsetInBits() % 8) == 0 && "Unnamed bitfield member!");
+  unsigned offset = DDTy->getOffsetInBits() / 8;
+  const DIType *Ty = DDTy->getBaseType().resolve();
+  assert(dyn_cast<DICompositeType>(Ty) && "Expects structure or union type");
+  const DICompositeType *DCTy = dyn_cast<DICompositeType>(Ty);
+  ClassInfo &NestedInfo = collectClassInfo(DCTy);
+  ClassInfo::MemberList &Members = NestedInfo.Members;
+  for (unsigned i = 0, e = Members.size(); i != e; ++i)
+    Info.Members.push_back(
+        {Members[i].MemberTypeNode, Members[i].BaseOffset + offset});
+}
+
+ClassInfo &CodeViewDebug::collectClassInfo(const DICompositeType *Ty) {
+  auto Insertion = ClassInfoMap.insert({Ty, std::unique_ptr<ClassInfo>()});
+  std::unique_ptr<ClassInfo> &Info = Insertion.first->second;
+  if (!Insertion.second)
+    return *Info;
+  Info.reset(new ClassInfo());
+
+  // Add elements to structure type.
+  DINodeArray Elements = Ty->getElements();
+  for (auto *Element : Elements) {
+    // We assume that the frontend provides all members in source declaration
+    // order, which is what MSVC does.
+    if (!Element)
+      continue;
+    if (auto *SP = dyn_cast<DISubprogram>(Element)) {
+      // Non-virtual methods does not need the introduced marker.
+      // Set it to false.
+      bool Introduced = false;
+      Info->Methods[SP->getRawName()].push_back({SP, Introduced});
+    } else if (auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
+      if (DDTy->getTag() == dwarf::DW_TAG_member)
+        collectMemberInfo(*Info, DDTy);
+      else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
+        // FIXME: collect class info from inheritance.
+      } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
+        // Ignore friend members. It appears that MSVC emitted info about
+        // friends in the past, but modern versions do not.
+      }
+      // FIXME: Get Clang to emit function virtual table here and handle it.
+      // FIXME: Get clang to emit nested types here and do something with
+      // them.
+    }
+    // Skip other unrecognized kinds of elements.
+  }
+
+  return *Info;
+}
+
 TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
   // First, construct the forward decl.  Don't look into Ty to compute the
   // forward decl options, since it might not be available in all TUs.
@@ -1170,15 +1361,15 @@ TypeIndex CodeViewDebug::lowerCompleteTy
   TypeRecordKind Kind = getRecordKind(Ty);
   // FIXME: Other ClassOptions, like ContainsNestedClass and NestedClass.
   ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
-  TypeIndex FTI;
+  TypeIndex FieldTI;
+  TypeIndex VShapeTI;
   unsigned FieldCount;
-  std::tie(FTI, FieldCount) = lowerRecordFieldList(Ty);
+  std::tie(FieldTI, VShapeTI, FieldCount) = lowerRecordFieldList(Ty);
 
   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
-  return TypeTable.writeClass(ClassRecord(Kind, FieldCount, CO, HfaKind::None,
-                                          WindowsRTClassKind::None, FTI,
-                                          TypeIndex(), TypeIndex(), SizeInBytes,
-                                          Ty->getName(), Ty->getIdentifier()));
+  return TypeTable.writeClass(ClassRecord(
+      Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
+      TypeIndex(), VShapeTI, SizeInBytes, Ty->getName(), Ty->getIdentifier()));
   // FIXME: Make an LF_UDT_SRC_LINE record.
 }
 
@@ -1193,65 +1384,89 @@ TypeIndex CodeViewDebug::lowerTypeUnion(
 
 TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
   ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
-  TypeIndex FTI;
+  TypeIndex FieldTI;
   unsigned FieldCount;
-  std::tie(FTI, FieldCount) = lowerRecordFieldList(Ty);
+  std::tie(FieldTI, std::ignore, FieldCount) = lowerRecordFieldList(Ty);
   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
-  return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None, FTI,
-                                          SizeInBytes, Ty->getName(),
+  return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None,
+                                          FieldTI, SizeInBytes, Ty->getName(),
                                           Ty->getIdentifier()));
   // FIXME: Make an LF_UDT_SRC_LINE record.
 }
 
-std::pair<TypeIndex, unsigned>
+std::tuple<TypeIndex, TypeIndex, unsigned>
 CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
   // Manually count members. MSVC appears to count everything that generates a
   // field list record. Each individual overload in a method overload group
   // contributes to this count, even though the overload group is a single field
   // list record.
   unsigned MemberCount = 0;
+  ClassInfo &Info = collectClassInfo(Ty);
   FieldListRecordBuilder Fields;
-  for (const DINode *Element : Ty->getElements()) {
-    // We assume that the frontend provides all members in source declaration
-    // order, which is what MSVC does.
-    if (!Element)
+
+  // Create members.
+  for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
+    const DIDerivedType *Member = MemberInfo.MemberTypeNode;
+    TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
+
+    if (Member->isStaticMember()) {
+      Fields.writeStaticDataMember(StaticDataMemberRecord(
+          translateAccessFlags(Ty->getTag(), Member->getFlags()),
+          MemberBaseType, Member->getName()));
+      MemberCount++;
       continue;
-    if (auto *SP = dyn_cast<DISubprogram>(Element)) {
-      // C++ method.
-      // FIXME: Overloaded methods are grouped together, so we'll need two
-      // passes to group them.
-      (void)SP;
-    } else if (auto *Member = dyn_cast<DIDerivedType>(Element)) {
-      if (Member->getTag() == dwarf::DW_TAG_member) {
-        if (Member->isStaticMember()) {
-          // Static data member.
-          Fields.writeStaticDataMember(StaticDataMemberRecord(
-              translateAccessFlags(Ty->getTag(), Member),
-              getTypeIndex(Member->getBaseType()), Member->getName()));
-          MemberCount++;
-        } else {
-          // Data member.
-          // FIXME: Make a BitFieldRecord for bitfields.
-          Fields.writeDataMember(DataMemberRecord(
-              translateAccessFlags(Ty->getTag(), Member),
-              getTypeIndex(Member->getBaseType()),
-              Member->getOffsetInBits() / 8, Member->getName()));
-          MemberCount++;
-        }
-      } else if (Member->getTag() == dwarf::DW_TAG_friend) {
-        // Ignore friend members. It appears that MSVC emitted info about
-        // friends in the past, but modern versions do not.
-      }
-      // FIXME: Get clang to emit nested types here and do something with
-      // them.
     }
-    // Skip other unrecognized kinds of elements.
+
+    uint64_t OffsetInBytes = MemberInfo.BaseOffset;
+
+    // FIXME: Handle bitfield type memeber.
+    OffsetInBytes += Member->getOffsetInBits() / 8;
+
+    Fields.writeDataMember(
+        DataMemberRecord(translateAccessFlags(Ty->getTag(), Member->getFlags()),
+                         MemberBaseType, OffsetInBytes, Member->getName()));
+    MemberCount++;
+  }
+
+  // Create methods
+  for (auto &MethodItr : Info.Methods) {
+    StringRef Name = MethodItr.first->getString();
+
+    std::vector<OneMethodRecord> Methods;
+    for (ClassInfo::MethodInfo &MethodInfo : MethodItr.second) {
+      const DISubprogram *SP = MethodInfo.Method;
+      bool Introduced = MethodInfo.Introduced;
+
+      TypeIndex MethodType = getTypeIndex(SP->getType(), Ty);
+
+      unsigned VFTableOffset = -1;
+      if (Introduced)
+        VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
+
+      Methods.push_back(
+          OneMethodRecord(MethodType, translateMethodKindFlags(SP, Introduced),
+                          translateMethodOptionFlags(SP),
+                          translateAccessFlags(Ty->getTag(), SP->getFlags()),
+                          VFTableOffset, Name));
+      MemberCount++;
+    }
+    assert(Methods.size() > 0 && "Empty methods map entry");
+    if (Methods.size() == 1)
+      Fields.writeOneMethod(Methods[0]);
+    else {
+      TypeIndex MethodList =
+          TypeTable.writeMethodOverloadList(MethodOverloadListRecord(Methods));
+      Fields.writeOverloadedMethod(
+          OverloadedMethodRecord(Methods.size(), MethodList, Name));
+    }
   }
-  return {TypeTable.writeFieldList(Fields), MemberCount};
+  TypeIndex FieldTI = TypeTable.writeFieldList(Fields);
+  return std::make_tuple(FieldTI, TypeIndex(), MemberCount);
 }
 
-TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef) {
+TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
   const DIType *Ty = TypeRef.resolve();
+  const DIType *ClassTy = ClassTyRef.resolve();
 
   // The null DIType is the void type. Don't try to hash it.
   if (!Ty)
@@ -1260,13 +1475,13 @@ TypeIndex CodeViewDebug::getTypeIndex(DI
   // Check if we've already translated this type. Don't try to do a
   // get-or-create style insertion that caches the hash lookup across the
   // lowerType call. It will update the TypeIndices map.
-  auto I = TypeIndices.find(Ty);
+  auto I = TypeIndices.find({Ty, ClassTy});
   if (I != TypeIndices.end())
     return I->second;
 
-  TypeIndex TI = lowerType(Ty);
+  TypeIndex TI = lowerType(Ty, ClassTy);
 
-  recordTypeIndexForDINode(Ty, TI);
+  recordTypeIndexForDINode(Ty, TI, ClassTy);
   return TI;
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Sat Jun 18 05:25:07 2016
@@ -31,6 +31,7 @@ namespace llvm {
 
 class StringRef;
 class LexicalScope;
+struct ClassInfo;
 
 /// \brief Collects and handles line tables information in a CodeView format.
 class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
@@ -136,14 +137,21 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   /// All inlined subprograms in the order they should be emitted.
   SmallSetVector<const DISubprogram *, 4> InlinedSubprograms;
 
-  /// Map from DI metadata nodes to CodeView type indices. Primarily indexed by
-  /// DIType* and DISubprogram*.
-  DenseMap<const DINode *, codeview::TypeIndex> TypeIndices;
+  /// Map from a pair of DI metadata nodes and its DI type (or scope) that can
+  /// be nullptr, to CodeView type indices. Primarily indexed by
+  /// {DIType*, DIType*} and {DISubprogram*, DIType*}.
+  ///
+  /// The second entry in the key is needed for methods as DISubroutineType
+  /// representing static method type are shared with non-method function type.
+  DenseMap<std::pair<const DINode *, const DIType *>, codeview::TypeIndex>
+      TypeIndices;
 
   /// Map from DICompositeType* to complete type index. Non-record types are
   /// always looked up in the normal TypeIndices map.
   DenseMap<const DICompositeType *, codeview::TypeIndex> CompleteTypeIndices;
 
+  /// Map from DICompositeType* to class info.
+  DenseMap<const DICompositeType *, std::unique_ptr<ClassInfo>> ClassInfoMap;
   const DISubprogram *CurrentSubprogram = nullptr;
 
   // The UDTs we have seen while processing types; each entry is a pair of type
@@ -159,14 +167,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
 
   void maybeRecordLocation(const DebugLoc &DL, const MachineFunction *MF);
 
-  void clear() {
-    assert(CurFn == nullptr);
-    FileIdMap.clear();
-    FnDebugInfo.clear();
-    FileToFilepathMap.clear();
-    LocalUDTs.clear();
-    GlobalUDTs.clear();
-  }
+  void clear();
 
   void setCurrentSubprogram(const DISubprogram *SP) {
     CurrentSubprogram = SP;
@@ -214,9 +215,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
 
   /// Translates the DIType to codeview if necessary and returns a type index
   /// for it.
-  codeview::TypeIndex getTypeIndex(DITypeRef TypeRef);
+  codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
+                                   DITypeRef ClassTyRef = DITypeRef());
 
-  codeview::TypeIndex lowerType(const DIType *Ty);
+  codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
   codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
   codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
   codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
@@ -224,6 +226,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty);
   codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
   codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
+  codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty,
+                                              const DIType *ClassTy);
   codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
   codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
   codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
@@ -238,14 +242,22 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
   codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
 
+  codeview::TypeIndex lowerSubprogramType(const DISubprogram *SP);
+
+  void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy);
+  ClassInfo &collectClassInfo(const DICompositeType *Ty);
+
   /// Common record member lowering functionality for record types, which are
   /// structs, classes, and unions. Returns the field list index and the member
   /// count.
-  std::pair<codeview::TypeIndex, unsigned>
+  std::tuple<codeview::TypeIndex, codeview::TypeIndex, unsigned>
   lowerRecordFieldList(const DICompositeType *Ty);
 
-  /// Inserts {Node, TI} into TypeIndices and checks for duplicates.
-  void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI);
+  /// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates.
+  void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI,
+                                const DIType *ClassTy = nullptr);
+
+  unsigned getPointerSizeInBytes();
 
 public:
   CodeViewDebug(AsmPrinter *Asm);

Modified: llvm/trunk/test/DebugInfo/COFF/types-basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-basic.ll?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-basic.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/types-basic.ll Sat Jun 18 05:25:07 2016
@@ -115,23 +115,25 @@
 ; CHECK:   }
 ; CHECK:   ArgList (0x1008) {
 ; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
-; CHECK:     NumArgs: 1
+; CHECK:     NumArgs: 0
 ; CHECK:     Arguments [
-; CHECK:       ArgType: A* (0x1007)
-; CHECK:     ]
-; CHECK:   }
-; CHECK:   Procedure (0x1009) {
-; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
-; CHECK:     ReturnType: void (0x3)
-; CHECK:     CallingConvention: NearC (0x0)
-; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
-; CHECK:     NumParameters: 1
-; CHECK:     ArgListType: (A*) (0x1008)
 ; CHECK:   }
+; CHECK:  MemberFunction (0x1009) {
+; CHECK:    TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK:    ReturnType: void (0x3)
+; CHECK:    ClassType: A (0x1005)
+; CHECK:    ThisType: A* (0x1007)
+; CHECK:    CallingConvention: NearC (0x0)
+; CHECK:    FunctionOptions [ (0x0)
+; CHECK:    ]
+; CHECK:    NumParameters: 0
+; CHECK:    ArgListType: () (0x1008)
+; CHECK:    ThisAdjustment: 0
+; CHECK:  }
 ; CHECK:   Pointer (0x100A) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (A*) (0x1009)
+; CHECK:     PointeeType: void A::() (0x1009)
 ; CHECK:     PointerAttributes: 0x1006C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)
@@ -160,25 +162,19 @@
 ; CHECK:     IsVolatile: 0
 ; CHECK:     IsUnaligned: 0
 ; CHECK:   }
-; CHECK:   ArgList (0x100D) {
-; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
-; CHECK:     NumArgs: 0
-; CHECK:     Arguments [
-; CHECK:     ]
-; CHECK:   }
-; CHECK:   Procedure (0x100E) {
+; CHECK:   Procedure (0x100D) {
 ; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
 ; CHECK:     ReturnType: void (0x3)
 ; CHECK:     CallingConvention: NearC (0x0)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
 ; CHECK:     NumParameters: 0
-; CHECK:     ArgListType: () (0x100D)
+; CHECK:     ArgListType: () (0x1008)
 ; CHECK:   }
-; CHECK:   FuncId (0x100F) {
+; CHECK:   FuncId (0x100E) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void () (0x100E)
+; CHECK:     FunctionType: void () (0x100D)
 ; CHECK:     Name: CharTypes
 ; CHECK:   }
 ; CHECK: ]
@@ -239,7 +235,7 @@
 ; CHECK:       VarName: v4
 ; CHECK:     }
 ; CHECK:     Local {
-; CHECK:       Type: void (A*) A::* (0x100A)
+; CHECK:       Type: void A::() A::* (0x100A)
 ; CHECK:       VarName: v5
 ; CHECK:     }
 ; CHECK:     Local {
@@ -267,7 +263,7 @@
 ; CHECK:   ]
 ; CHECK:   Subsection [
 ; CHECK:     ProcStart {
-; CHECK:       Type: CharTypes (0x100F)
+; CHECK:       Type: CharTypes (0x100E)
 ; CHECK:       DisplayName: CharTypes
 ; CHECK:       LinkageName: ?CharTypes@@YAXXZ
 ; CHECK:     }

Modified: llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll Sat Jun 18 05:25:07 2016
@@ -40,90 +40,85 @@
 ; CHECK:   }
 ; CHECK:   ArgList (0x1002) {
 ; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
-; CHECK:     NumArgs: 1
+; CHECK:     NumArgs: 0
 ; CHECK:     Arguments [
-; CHECK:       ArgType: A* (0x1001)
 ; CHECK:     ]
 ; CHECK:   }
-; CHECK:   Procedure (0x1003) {
-; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:   MemberFunction (0x1003) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
 ; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: A (0x1000)
+; CHECK:     ThisType: A* (0x1001)
 ; CHECK:     CallingConvention: ThisCall (0xB)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
-; CHECK:     NumParameters: 1
-; CHECK:     ArgListType: (A*) (0x1002)
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1002)
 ; CHECK:   }
 ; CHECK:   FuncId (0x1004) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void (A*) (0x1003)
+; CHECK:     FunctionType: void A::() (0x1003)
 ; CHECK:     Name: A::thiscallcc
 ; CHECK:   }
-; CHECK:   ArgList (0x1005) {
-; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
-; CHECK:     NumArgs: 0
-; CHECK:     Arguments [
-; CHECK:     ]
-; CHECK:   }
-; CHECK:   Procedure (0x1006) {
+; CHECK:   Procedure (0x1005) {
 ; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
 ; CHECK:     ReturnType: void (0x3)
 ; CHECK:     CallingConvention: NearC (0x0)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
 ; CHECK:     NumParameters: 0
-; CHECK:     ArgListType: () (0x1005)
+; CHECK:     ArgListType: () (0x1002)
 ; CHECK:   }
-; CHECK:   FuncId (0x1007) {
+; CHECK:   FuncId (0x1006) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void () (0x1006)
+; CHECK:     FunctionType: void () (0x1005)
 ; CHECK:     Name: cdeclcc
 ; CHECK:   }
-; CHECK:   Procedure (0x1008) {
+; CHECK:   Procedure (0x1007) {
 ; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
 ; CHECK:     ReturnType: void (0x3)
 ; CHECK:     CallingConvention: NearFast (0x4)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
 ; CHECK:     NumParameters: 0
-; CHECK:     ArgListType: () (0x1005)
+; CHECK:     ArgListType: () (0x1002)
 ; CHECK:   }
-; CHECK:   FuncId (0x1009) {
+; CHECK:   FuncId (0x1008) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void () (0x1008)
+; CHECK:     FunctionType: void () (0x1007)
 ; CHECK:     Name: fastcallcc
 ; CHECK:   }
-; CHECK:   Procedure (0x100A) {
+; CHECK:   Procedure (0x1009) {
 ; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
 ; CHECK:     ReturnType: void (0x3)
 ; CHECK:     CallingConvention: NearStdCall (0x7)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
 ; CHECK:     NumParameters: 0
-; CHECK:     ArgListType: () (0x1005)
+; CHECK:     ArgListType: () (0x1002)
 ; CHECK:   }
-; CHECK:   FuncId (0x100B) {
+; CHECK:   FuncId (0x100A) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void () (0x100A)
+; CHECK:     FunctionType: void () (0x1009)
 ; CHECK:     Name: stdcallcc
 ; CHECK:   }
-; CHECK:   Procedure (0x100C) {
+; CHECK:   Procedure (0x100B) {
 ; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
 ; CHECK:     ReturnType: void (0x3)
 ; CHECK:     CallingConvention: NearVector (0x18)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
 ; CHECK:     NumParameters: 0
-; CHECK:     ArgListType: () (0x1005)
+; CHECK:     ArgListType: () (0x1002)
 ; CHECK:   }
-; CHECK:   FuncId (0x100D) {
+; CHECK:   FuncId (0x100C) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void () (0x100C)
+; CHECK:     FunctionType: void () (0x100B)
 ; CHECK:     Name: vectorcallcc
 ; CHECK:   }
 ; CHECK: ]

Modified: llvm/trunk/test/DebugInfo/COFF/types-data-members.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-data-members.ll?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-data-members.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/types-data-members.ll Sat Jun 18 05:25:07 2016
@@ -324,26 +324,22 @@
 ; CHECK:     IsVolatile: 0
 ; CHECK:     IsUnaligned: 0
 ; CHECK:   }
-; CHECK:   ArgList (0x1017) {
-; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
-; CHECK:     NumArgs: 1
-; CHECK:     Arguments [
-; CHECK:       ArgType: DerivedClass* (0x1016)
-; CHECK:     ]
-; CHECK:   }
-; CHECK:   Procedure (0x1018) {
-; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:   MemberFunction (0x1017) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
 ; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: DerivedClass (0x100D)
+; CHECK:     ThisType: DerivedClass* (0x1016)
 ; CHECK:     CallingConvention: NearC (0x0)
 ; CHECK:     FunctionOptions [ (0x0)
 ; CHECK:     ]
-; CHECK:     NumParameters: 1
-; CHECK:     ArgListType: (DerivedClass*) (0x1017)
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1000)
+; CHECK:     ThisAdjustment: 0
 ; CHECK:   }
-; CHECK:   FuncId (0x1019) {
+; CHECK:   FuncId (0x1018) {
 ; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
 ; CHECK:     ParentScope: 0x0
-; CHECK:     FunctionType: void (DerivedClass*) (0x1018)
+; CHECK:     FunctionType: void DerivedClass::() (0x1017)
 ; CHECK:     Name: DerivedClass::DerivedClass
 ; CHECK:   }
 ; CHECK: ]

Added: llvm/trunk/test/DebugInfo/COFF/types-non-virtual-methods.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-non-virtual-methods.ll?rev=273084&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-non-virtual-methods.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/types-non-virtual-methods.ll Sat Jun 18 05:25:07 2016
@@ -0,0 +1,295 @@
+; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
+
+; C++ source to regenerate:
+; $ cat t.cpp
+; struct A {
+;   void f_default_public();
+; private:
+;   void f_private();
+; protected:
+;   void f_protected();
+; public:
+;   void f_public();
+; };
+;
+; class B {
+;  void f_default_private();
+; public:
+;   void f(float);
+;   void f(int);
+; };
+;
+; void foo() {
+;   A a;
+;   B b;
+; }
+
+
+; CHECK: CodeViewTypes [
+; CHECK:   Section: .debug$T (5)
+; CHECK:   Magic: 0x4
+; CHECK:   ArgList (0x1000) {
+; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
+; CHECK:     NumArgs: 0
+; CHECK:     Arguments [
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   Procedure (0x1001) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: NearC (0x0)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1000)
+; CHECK:   }
+; CHECK:   FuncId (0x1002) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void () (0x1001)
+; CHECK:     Name: foo
+; CHECK:   }
+; CHECK:   Struct (0x1003) {
+; CHECK:     TypeLeafKind: LF_STRUCTURE (0x1505)
+; CHECK:     MemberCount: 0
+; CHECK:     Properties [ (0x80)
+; CHECK:       ForwardReference (0x80)
+; CHECK:     ]
+; CHECK:     FieldList: 0x0
+; CHECK:     DerivedFrom: 0x0
+; CHECK:     VShape: 0x0
+; CHECK:     SizeOf: 0
+; CHECK:     Name: A
+; CHECK:   }
+; CHECK:   Pointer (0x1004) {
+; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
+; CHECK:     PointeeType: A (0x1003)
+; CHECK:     PointerAttributes: 0x800A
+; CHECK:     PtrType: Near32 (0xA)
+; CHECK:     PtrMode: Pointer (0x0)
+; CHECK:     IsFlat: 0
+; CHECK:     IsConst: 0
+; CHECK:     IsVolatile: 0
+; CHECK:     IsUnaligned: 0
+; CHECK:   }
+; CHECK:   MemberFunction (0x1005) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: A (0x1003)
+; CHECK:     ThisType: A* (0x1004)
+; CHECK:     CallingConvention: ThisCall (0xB)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1000)
+; CHECK:     ThisAdjustment: 0
+; CHECK:   }
+; CHECK:   UnknownLeaf (0x1006) {
+; CHECK:     TypeLeafKind: LF_FIELDLIST (0x1203)
+; CHECK:     OneMethod {
+; CHECK:       AccessSpecifier: Public (0x3)
+; CHECK:       Type: void A::() (0x1005)
+; CHECK:       Name: A::f_default_public
+; CHECK:     }
+; CHECK:     OneMethod {
+; CHECK:       AccessSpecifier: Private (0x1)
+; CHECK:       Type: void A::() (0x1005)
+; CHECK:       Name: A::f_private
+; CHECK:     }
+; CHECK:     OneMethod {
+; CHECK:       AccessSpecifier: Protected (0x2)
+; CHECK:       Type: void A::() (0x1005)
+; CHECK:       Name: A::f_protected
+; CHECK:     }
+; CHECK:     OneMethod {
+; CHECK:       AccessSpecifier: Public (0x3)
+; CHECK:       Type: void A::() (0x1005)
+; CHECK:       Name: A::f_public
+; CHECK:     }
+; CHECK:   }
+; CHECK:   Struct (0x1007) {
+; CHECK:     TypeLeafKind: LF_STRUCTURE (0x1505)
+; CHECK:     MemberCount: 4
+; CHECK:     Properties [ (0x0)
+; CHECK:     ]
+; CHECK:     FieldList: A::f_public (0x1006)
+; CHECK:     DerivedFrom: 0x0
+; CHECK:     VShape: 0x0
+; CHECK:     SizeOf: 1
+; CHECK:     Name: A
+; CHECK:   }
+; CHECK:   Class (0x1008) {
+; CHECK:     TypeLeafKind: LF_CLASS (0x1504)
+; CHECK:     MemberCount: 0
+; CHECK:     Properties [ (0x80)
+; CHECK:       ForwardReference (0x80)
+; CHECK:     ]
+; CHECK:     FieldList: 0x0
+; CHECK:     DerivedFrom: 0x0
+; CHECK:     VShape: 0x0
+; CHECK:     SizeOf: 0
+; CHECK:     Name: B
+; CHECK:   }
+; CHECK:   Pointer (0x1009) {
+; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
+; CHECK:     PointeeType: B (0x1008)
+; CHECK:     PointerAttributes: 0x800A
+; CHECK:     PtrType: Near32 (0xA)
+; CHECK:     PtrMode: Pointer (0x0)
+; CHECK:     IsFlat: 0
+; CHECK:     IsConst: 0
+; CHECK:     IsVolatile: 0
+; CHECK:     IsUnaligned: 0
+; CHECK:   }
+; CHECK:   MemberFunction (0x100A) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: B (0x1008)
+; CHECK:     ThisType: B* (0x1009)
+; CHECK:     CallingConvention: ThisCall (0xB)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1000)
+; CHECK:     ThisAdjustment: 0
+; CHECK:   }
+; CHECK:   ArgList (0x100B) {
+; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
+; CHECK:     NumArgs: 1
+; CHECK:     Arguments [
+; CHECK:       ArgType: float (0x40)
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   MemberFunction (0x100C) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: B (0x1008)
+; CHECK:     ThisType: B* (0x1009)
+; CHECK:     CallingConvention: ThisCall (0xB)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 1
+; CHECK:     ArgListType: (float) (0x100B)
+; CHECK:     ThisAdjustment: 0
+; CHECK:   }
+; CHECK:   ArgList (0x100D) {
+; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
+; CHECK:     NumArgs: 1
+; CHECK:     Arguments [
+; CHECK:       ArgType: int (0x74)
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   MemberFunction (0x100E) {
+; CHECK:     TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     ClassType: B (0x1008)
+; CHECK:     ThisType: B* (0x1009)
+; CHECK:     CallingConvention: ThisCall (0xB)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 1
+; CHECK:     ArgListType: (int) (0x100D)
+; CHECK:     ThisAdjustment: 0
+; CHECK:   }
+; CHECK:   MethodOverloadList (0x100F) {
+; CHECK:     TypeLeafKind: LF_METHODLIST (0x1206)
+; CHECK:     Method [
+; CHECK:       AccessSpecifier: Public (0x3)
+; CHECK:       Type: void B::(float) (0x100C)
+; CHECK:     ]
+; CHECK:     Method [
+; CHECK:       AccessSpecifier: Public (0x3)
+; CHECK:       Type: void B::(int) (0x100E)
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   UnknownLeaf (0x1010) {
+; CHECK:     TypeLeafKind: LF_FIELDLIST (0x1203)
+; CHECK:     OneMethod {
+; CHECK:       AccessSpecifier: Private (0x1)
+; CHECK:       Type: void B::() (0x100A)
+; CHECK:       Name: B::f_default_private
+; CHECK:     }
+; CHECK:     OverloadedMethod {
+; CHECK:       MethodCount: 0x2
+; CHECK:       MethodListIndex: 0x100F
+; CHECK:       Name: B::f
+; CHECK:     }
+; CHECK:   }
+; CHECK:   Class (0x1011) {
+; CHECK:     TypeLeafKind: LF_CLASS (0x1504)
+; CHECK:     MemberCount: 3
+; CHECK:     Properties [ (0x0)
+; CHECK:     ]
+; CHECK:     FieldList: B::f (0x1010)
+; CHECK:     DerivedFrom: 0x0
+; CHECK:     VShape: 0x0
+; CHECK:     SizeOf: 1
+; CHECK:     Name: B
+; CHECK:   }
+; CHECK: ]
+
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+%struct.A = type { i8 }
+%class.B = type { i8 }
+
+; Function Attrs: nounwind
+define void @"\01?foo@@YAXXZ"() #0 !dbg !6 {
+entry:
+  %a = alloca %struct.A, align 1
+  %b = alloca %class.B, align 1
+  call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !9, metadata !19), !dbg !20
+  call void @llvm.dbg.declare(metadata %class.B* %b, metadata !21, metadata !19), !dbg !36
+  ret void, !dbg !37
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 272316)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.cpp", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"CodeView", i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang version 3.9.0 (trunk 272316)"}
+!6 = distinct !DISubprogram(name: "foo", linkageName: "\01?foo@@YAXXZ", scope: !1, file: !1, line: 18, type: !7, isLocal: false, isDefinition: true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!7 = !DISubroutineType(types: !8)
+!8 = !{null}
+!9 = !DILocalVariable(name: "a", scope: !6, file: !1, line: 19, type: !10)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 8, align: 8, elements: !11)
+!11 = !{!12, !16, !17, !18}
+!12 = !DISubprogram(name: "A::f_default_public", linkageName: "\01?f_default_public at A@@QAEXXZ", scope: !10, file: !1, line: 2, type: !13, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false)
+!13 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !14)
+!14 = !{null, !15}
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+!16 = !DISubprogram(name: "A::f_private", linkageName: "\01?f_private at A@@AAEXXZ", scope: !10, file: !1, line: 4, type: !13, isLocal: false, isDefinition: false, scopeLine: 4, flags: DIFlagPrivate | DIFlagPrototyped, isOptimized: false)
+!17 = !DISubprogram(name: "A::f_protected", linkageName: "\01?f_protected at A@@IAEXXZ", scope: !10, file: !1, line: 6, type: !13, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagProtected | DIFlagPrototyped, isOptimized: false)
+!18 = !DISubprogram(name: "A::f_public", linkageName: "\01?f_public at A@@QAEXXZ", scope: !10, file: !1, line: 8, type: !13, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false)
+!19 = !DIExpression()
+!20 = !DILocation(line: 19, scope: !6)
+!21 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 20, type: !22)
+!22 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", file: !1, line: 11, size: 8, align: 8, elements: !23)
+!23 = !{!24, !28, !32}
+!24 = !DISubprogram(name: "B::f_default_private", linkageName: "\01?f_default_private at B@@AAEXXZ", scope: !22, file: !1, line: 12, type: !25, isLocal: false, isDefinition: false, scopeLine: 12, flags: DIFlagPrototyped, isOptimized: false)
+!25 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !26)
+!26 = !{null, !27}
+!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+!28 = !DISubprogram(name: "B::f", linkageName: "\01?f at B@@QAEXM at Z", scope: !22, file: !1, line: 14, type: !29, isLocal: false, isDefinition: false, scopeLine: 14, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: false)
+!29 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !30)
+!30 = !{null, !27, !31}
+!31 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
+!32 = !DISubprogram(name: "B::f", linkageName: "\01?f at B@@QAEXH at Z", scope: !22, file: !1, line: 15, type: !33, isLocal: false, isDefinition: false, scopeLine: 15, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: false)
+!33 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !34)
+!34 = !{null, !27, !35}
+!35 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!36 = !DILocation(line: 20, scope: !6)
+!37 = !DILocation(line: 21, scope: !6)

Modified: llvm/trunk/test/DebugInfo/COFF/types-ptr-to-member.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-ptr-to-member.ll?rev=273084&r1=273083&r2=273084&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-ptr-to-member.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/types-ptr-to-member.ll Sat Jun 18 05:25:07 2016
@@ -85,7 +85,7 @@
 
 ; CHECK:   Pointer ({{.*}}) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (A*)
+; CHECK:     PointeeType: void A::()
 ; CHECK:     PointerAttributes: 0x1006C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)
@@ -99,7 +99,7 @@
 ; CHECK:   }
 ; CHECK:   Pointer ({{.*}}) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (C*)
+; CHECK:     PointeeType: void C::()
 ; CHECK:     PointerAttributes: 0x2006C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)
@@ -113,7 +113,7 @@
 ; CHECK:   }
 ; CHECK:   Pointer ({{.*}}) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (D*)
+; CHECK:     PointeeType: void D::()
 ; CHECK:     PointerAttributes: 0x2006C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)
@@ -127,7 +127,7 @@
 ; CHECK:   }
 ; CHECK:   Pointer ({{.*}}) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (E*)
+; CHECK:     PointeeType: void E::()
 ; CHECK:     PointerAttributes: 0x3006C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)
@@ -159,7 +159,7 @@
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
 ; CHECK:   Pointer ({{.*}}) {
 ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
-; CHECK:     PointeeType: void (Incomplete*)
+; CHECK:     PointeeType: void Incomplete::()
 ; CHECK:     PointerAttributes: 0x6C
 ; CHECK:     PtrType: Near64 (0xC)
 ; CHECK:     PtrMode: PointerToMemberFunction (0x3)




More information about the llvm-commits mailing list