[llvm] r274325 - [codeview] Add DISubprogram::ThisAdjustment

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 30 19:41:21 PDT 2016


Author: rnk
Date: Thu Jun 30 21:41:21 2016
New Revision: 274325

URL: http://llvm.org/viewvc/llvm-project?rev=274325&view=rev
Log:
[codeview] Add DISubprogram::ThisAdjustment

Summary:
This represents the adjustment applied to the implicit 'this' parameter
in the prologue of a virtual method in the MS C++ ABI. The adjustment is
always zero unless multiple inheritance is involved.

This increases the size of DISubprogram by 8 bytes, unfortunately. The
adjustment really is a signed 32-bit integer. If this size increase is
too much, we could probably win it back by splitting out a subclass with
info specific to virtual methods (virtuality, vindex, thisadjustment,
containingType).

Reviewers: aprantl, dexonsmith

Subscribers: aaboud, amccarth, llvm-commits

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

Added:
    llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll
    llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll.bc
    llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll
Modified:
    llvm/trunk/include/llvm/IR/DIBuilder.h
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/IR/DIBuilder.cpp
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.h
    llvm/trunk/test/Assembler/disubprogram.ll
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/DIBuilder.h Thu Jun 30 21:41:21 2016
@@ -560,6 +560,9 @@ namespace llvm {
     ///                      virtual function.
     /// \param VTableIndex   Index no of this method in virtual table, or -1u if
     ///                      unrepresentable.
+    /// \param ThisAdjustment
+    ///                      MS ABI-specific adjustment of 'this' that occurs
+    ///                      in the prologue.
     /// \param VTableHolder  Type that holds vtable.
     /// \param Flags         e.g. is this function prototyped or not.
     ///                      This flags are used to emit dwarf attributes.
@@ -569,8 +572,9 @@ namespace llvm {
     createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName,
                  DIFile *File, unsigned LineNo, DISubroutineType *Ty,
                  bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0,
-                 unsigned VTableIndex = 0, DIType *VTableHolder = nullptr,
-                 unsigned Flags = 0, bool isOptimized = false,
+                 unsigned VTableIndex = 0, int ThisAdjustment = 0,
+                 DIType *VTableHolder = nullptr, unsigned Flags = 0,
+                 bool isOptimized = false,
                  DITemplateParameterArray TParams = nullptr);
 
     /// This creates new descriptor for a namespace with the specified

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Thu Jun 30 21:41:21 2016
@@ -1280,6 +1280,11 @@ class DISubprogram : public DILocalScope
   unsigned ScopeLine;
   unsigned VirtualIndex;
 
+  /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue
+  /// of method overrides from secondary bases by this amount. It may be
+  /// negative.
+  int ThisAdjustment;
+
   // Virtuality can only assume three values, so we can pack
   // in 2 bits (none/pure/pure_virtual).
   unsigned Virtuality : 2;
@@ -1296,13 +1301,14 @@ class DISubprogram : public DILocalScope
 
   DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
                unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex,
-               unsigned Flags, bool IsLocalToUnit, bool IsDefinition,
-               bool IsOptimized, ArrayRef<Metadata *> Ops)
+               int ThisAdjustment, unsigned Flags, bool IsLocalToUnit,
+               bool IsDefinition, bool IsOptimized, ArrayRef<Metadata *> Ops)
       : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram,
                      Ops),
         Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),
-        Virtuality(Virtuality), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
-        IsDefinition(IsDefinition), IsOptimized(IsOptimized) {
+        ThisAdjustment(ThisAdjustment), Virtuality(Virtuality), Flags(Flags),
+        IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition),
+        IsOptimized(IsOptimized) {
     static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range");
     assert(Virtuality < 4 && "Virtuality out of range");
     assert((Flags < (1 << 27)) && "Flags out of range");
@@ -1314,33 +1320,34 @@ class DISubprogram : public DILocalScope
           StringRef LinkageName, DIFile *File, unsigned Line,
           DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
           unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality,
-          unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-          DICompileUnit *Unit, DITemplateParameterArray TemplateParams,
-          DISubprogram *Declaration, DILocalVariableArray Variables,
-          StorageType Storage, bool ShouldCreate = true) {
+          unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+          bool IsOptimized, DICompileUnit *Unit,
+          DITemplateParameterArray TemplateParams, DISubprogram *Declaration,
+          DILocalVariableArray Variables, StorageType Storage,
+          bool ShouldCreate = true) {
     return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
                    getCanonicalMDString(Context, LinkageName), File, Line, Type,
                    IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
-                   Virtuality, VirtualIndex, Flags, IsOptimized, Unit,
-                   TemplateParams.get(), Declaration, Variables.get(), Storage,
-                   ShouldCreate);
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams.get(), Declaration, Variables.get(),
+                   Storage, ShouldCreate);
   }
   static DISubprogram *
   getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
           MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
           bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
           Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
-          unsigned Flags, bool IsOptimized, Metadata *Unit,
+          int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit,
           Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
           StorageType Storage, bool ShouldCreate = true);
 
   TempDISubprogram cloneImpl() const {
-    return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
-                        getFile(), getLine(), getType(), isLocalToUnit(),
-                        isDefinition(), getScopeLine(), getContainingType(),
-                        getVirtuality(), getVirtualIndex(), getFlags(),
-                        isOptimized(), getUnit(), getTemplateParams(),
-                        getDeclaration(), getVariables());
+    return getTemporary(
+        getContext(), getScope(), getName(), getLinkageName(), getFile(),
+        getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(),
+        getContainingType(), getVirtuality(), getVirtualIndex(),
+        getThisAdjustment(), getFlags(), isOptimized(), getUnit(),
+        getTemplateParams(), getDeclaration(), getVariables());
   }
 
 public:
@@ -1349,26 +1356,26 @@ public:
                      DIFile *File, unsigned Line, DISubroutineType *Type,
                      bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
                      DITypeRef ContainingType, unsigned Virtuality,
-                     unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-                     DICompileUnit *Unit,
+                     unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+                     bool IsOptimized, DICompileUnit *Unit,
                      DITemplateParameterArray TemplateParams = nullptr,
                      DISubprogram *Declaration = nullptr,
                      DILocalVariableArray Variables = nullptr),
                     (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
                      IsDefinition, ScopeLine, ContainingType, Virtuality,
-                     VirtualIndex, Flags, IsOptimized, Unit, TemplateParams,
-                     Declaration, Variables))
+                     VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
+                     TemplateParams, Declaration, Variables))
   DEFINE_MDNODE_GET(
       DISubprogram,
       (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
        unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
        unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
-       unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-       Metadata *Unit, Metadata *TemplateParams = nullptr,
+       unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+       bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr,
        Metadata *Declaration = nullptr, Metadata *Variables = nullptr),
       (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
-       ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized,
-       Unit, TemplateParams, Declaration, Variables))
+       ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment,
+       Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables))
 
   TempDISubprogram clone() const { return cloneImpl(); }
 
@@ -1376,6 +1383,7 @@ public:
   unsigned getLine() const { return Line; }
   unsigned getVirtuality() const { return Virtuality; }
   unsigned getVirtualIndex() const { return VirtualIndex; }
+  int getThisAdjustment() const { return ThisAdjustment; }
   unsigned getScopeLine() const { return ScopeLine; }
   unsigned getFlags() const { return Flags; }
   bool isLocalToUnit() const { return IsLocalToUnit; }

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Thu Jun 30 21:41:21 2016
@@ -3983,7 +3983,7 @@ bool LLParser::ParseDICompileUnit(MDNode
 ///                     file: !1, line: 7, type: !2, isLocal: false,
 ///                     isDefinition: true, scopeLine: 8, containingType: !3,
 ///                     virtuality: DW_VIRTUALTIY_pure_virtual,
-///                     virtualIndex: 10, flags: 11,
+///                     virtualIndex: 10, thisAdjustment: 4, flags: 11,
 ///                     isOptimized: false, templateParams: !4, declaration: !5,
 ///                     variables: !6)
 bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) {
@@ -4001,6 +4001,7 @@ bool LLParser::ParseDISubprogram(MDNode
   OPTIONAL(containingType, MDField, );                                         \
   OPTIONAL(virtuality, DwarfVirtualityField, );                                \
   OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX));                    \
+  OPTIONAL(thisAdjustment, MDSignedField, (0, INT32_MIN, INT32_MAX));          \
   OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(isOptimized, MDBoolField, );                                        \
   OPTIONAL(unit, MDField, );                                                   \
@@ -4019,8 +4020,9 @@ bool LLParser::ParseDISubprogram(MDNode
       DISubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val,
                      line.Val, type.Val, isLocal.Val, isDefinition.Val,
                      scopeLine.Val, containingType.Val, virtuality.Val,
-                     virtualIndex.Val, flags.Val, isOptimized.Val, unit.Val,
-                     templateParams.Val, declaration.Val, variables.Val));
+                     virtualIndex.Val, thisAdjustment.Val, flags.Val,
+                     isOptimized.Val, unit.Val, templateParams.Val,
+                     declaration.Val, variables.Val));
   return false;
 }
 

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Jun 30 21:41:21 2016
@@ -2466,7 +2466,7 @@ std::error_code BitcodeReader::parseMeta
       break;
     }
     case bitc::METADATA_SUBPROGRAM: {
-      if (Record.size() != 18 && Record.size() != 19)
+      if (Record.size() < 18 || Record.size() > 20)
         return error("Invalid record");
 
       IsDistinct =
@@ -2474,21 +2474,36 @@ std::error_code BitcodeReader::parseMeta
       // Version 1 has a Function as Record[15].
       // Version 2 has removed Record[15].
       // Version 3 has the Unit as Record[15].
+      // Version 4 added thisAdjustment.
       bool HasUnit = Record[0] >= 2;
-      if (HasUnit && Record.size() != 19)
+      if (HasUnit && Record.size() < 19)
         return error("Invalid record");
       Metadata *CUorFn = getMDOrNull(Record[15]);
-      unsigned Offset = Record.size() == 19 ? 1 : 0;
+      unsigned Offset = Record.size() >= 19 ? 1 : 0;
       bool HasFn = Offset && !HasUnit;
+      bool HasThisAdj = Record.size() >= 20;
       DISubprogram *SP = GET_OR_DISTINCT(
-          DISubprogram,
-          (Context, getDITypeRefOrNull(Record[1]), getMDString(Record[2]),
-           getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
-           getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
-           getDITypeRefOrNull(Record[10]), Record[11], Record[12], Record[13],
-           Record[14], HasUnit ? CUorFn : nullptr,
-           getMDOrNull(Record[15 + Offset]), getMDOrNull(Record[16 + Offset]),
-           getMDOrNull(Record[17 + Offset])));
+          DISubprogram, (Context,
+                         getDITypeRefOrNull(Record[1]),    // scope
+                         getMDString(Record[2]),           // name
+                         getMDString(Record[3]),           // linkageName
+                         getMDOrNull(Record[4]),           // file
+                         Record[5],                        // line
+                         getMDOrNull(Record[6]),           // type
+                         Record[7],                        // isLocal
+                         Record[8],                        // isDefinition
+                         Record[9],                        // scopeLine
+                         getDITypeRefOrNull(Record[10]),   // containingType
+                         Record[11],                       // virtuality
+                         Record[12],                       // virtualIndex
+                         HasThisAdj ? Record[19] : 0,      // thisAdjustment
+                         Record[13],                       // flags
+                         Record[14],                       // isOptimized
+                         HasUnit ? CUorFn : nullptr,       // unit
+                         getMDOrNull(Record[15 + Offset]), // templateParams
+                         getMDOrNull(Record[16 + Offset]), // declaration
+                         getMDOrNull(Record[17 + Offset])  // variables
+                         ));
       MetadataList.assignValue(SP, NextMetadataNo++);
 
       // Upgrade sp->function mapping to function->sp mapping.

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu Jun 30 21:41:21 2016
@@ -1543,6 +1543,7 @@ void ModuleBitcodeWriter::writeDISubprog
   Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
   Record.push_back(VE.getMetadataOrNullID(N->getDeclaration()));
   Record.push_back(VE.getMetadataOrNullID(N->getVariables().get()));
+  Record.push_back(N->getThisAdjustment());
 
   Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev);
   Record.clear();

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Jun 30 21:41:21 2016
@@ -156,6 +156,18 @@ static std::string getFullyQualifiedName
   return getQualifiedName(QualifiedNameComponents, Name);
 }
 
+struct CodeViewDebug::TypeLoweringScope {
+  TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; }
+  ~TypeLoweringScope() {
+    // Don't decrement TypeEmissionLevel until after emitting deferred types, so
+    // inner TypeLoweringScopes don't attempt to emit deferred types.
+    if (CVD.TypeEmissionLevel == 1)
+      CVD.emitDeferredCompleteTypes();
+    --CVD.TypeEmissionLevel;
+  }
+  CodeViewDebug &CVD;
+};
+
 TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
   // No scope means global scope and that uses the zero index.
   if (!Scope || isa<DIFile>(Scope))
@@ -213,16 +225,24 @@ TypeIndex CodeViewDebug::getFuncIdForSub
 
 TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
                                                const DICompositeType *Class) {
+  // Always use the method declaration as the key for the function type. The
+  // method declaration contains the this adjustment.
+  if (SP->getDeclaration())
+    SP = SP->getDeclaration();
+  assert(!SP->getDeclaration() && "should use declaration as key");
+
   // Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide
   // with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}.
-  auto I = TypeIndices.find({SP, nullptr});
+  auto I = TypeIndices.find({SP, Class});
   if (I != TypeIndices.end())
     return I->second;
 
-  // FIXME: Get the ThisAdjustment off of SP when it is available.
+  // Make sure complete type info for the class is emitted *after* the member
+  // function type, as the complete class type is likely to reference this
+  // member function type.
+  TypeLoweringScope S(*this);
   TypeIndex TI =
-      lowerTypeMemberFunction(SP->getType(), Class, /*ThisAdjustment=*/0);
-
+      lowerTypeMemberFunction(SP->getType(), Class, SP->getThisAdjustment());
   return recordTypeIndexForDINode(SP, TI, Class);
 }
 
@@ -1582,18 +1602,6 @@ TypeIndex CodeViewDebug::getVBPTypeIndex
   return VBPType;
 }
 
-struct CodeViewDebug::TypeLoweringScope {
-  TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; }
-  ~TypeLoweringScope() {
-    // Don't decrement TypeEmissionLevel until after emitting deferred types, so
-    // inner TypeLoweringScopes don't attempt to emit deferred types.
-    if (CVD.TypeEmissionLevel == 1)
-      CVD.emitDeferredCompleteTypes();
-    --CVD.TypeEmissionLevel;
-  }
-  CodeViewDebug &CVD;
-};
-
 TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
   const DIType *Ty = TypeRef.resolve();
   const DIType *ClassTy = ClassTyRef.resolve();
@@ -1609,14 +1617,9 @@ TypeIndex CodeViewDebug::getTypeIndex(DI
   if (I != TypeIndices.end())
     return I->second;
 
-  TypeIndex TI;
-  {
-    TypeLoweringScope S(*this);
-    TI = lowerType(Ty, ClassTy);
-    recordTypeIndexForDINode(Ty, TI, ClassTy);
-  }
-
-  return TI;
+  TypeLoweringScope S(*this);
+  TypeIndex TI = lowerType(Ty, ClassTy);
+  return recordTypeIndexForDINode(Ty, TI, ClassTy);
 }
 
 TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Thu Jun 30 21:41:21 2016
@@ -1720,6 +1720,7 @@ static void writeDISubprogram(raw_ostrea
   if (N->getVirtuality() != dwarf::DW_VIRTUALITY_none ||
       N->getVirtualIndex() != 0)
     Printer.printInt("virtualIndex", N->getVirtualIndex(), false);
+  Printer.printInt("thisAdjustment", N->getThisAdjustment());
   Printer.printDIFlags("flags", N->getFlags());
   Printer.printBool("isOptimized", N->isOptimized());
   Printer.printMetadata("unit", N->getRawUnit());

Modified: llvm/trunk/lib/IR/DIBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DIBuilder.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DIBuilder.cpp (original)
+++ llvm/trunk/lib/IR/DIBuilder.cpp Thu Jun 30 21:41:21 2016
@@ -667,8 +667,8 @@ DISubprogram *DIBuilder::createFunction(
   auto *Node = getSubprogram(
       /* IsDistinct = */ isDefinition, VMContext,
       getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty,
-      isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, Flags, isOptimized,
-      isDefinition ? CUNode : nullptr, TParams, Decl,
+      isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, 0, Flags,
+      isOptimized, isDefinition ? CUNode : nullptr, TParams, Decl,
       MDTuple::getTemporary(VMContext, None).release());
 
   if (isDefinition)
@@ -685,8 +685,8 @@ DISubprogram *DIBuilder::createTempFunct
   return DISubprogram::getTemporary(
              VMContext, getNonCompileUnitScope(Context), Name, LinkageName,
              File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, nullptr,
-             0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr, TParams,
-             Decl, nullptr)
+             0, 0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr,
+             TParams, Decl, nullptr)
       .release();
 }
 
@@ -694,8 +694,9 @@ DISubprogram *
 DIBuilder::createMethod(DIScope *Context, StringRef Name, StringRef LinkageName,
                         DIFile *F, unsigned LineNo, DISubroutineType *Ty,
                         bool isLocalToUnit, bool isDefinition, unsigned VK,
-                        unsigned VIndex, DIType *VTableHolder, unsigned Flags,
-                        bool isOptimized, DITemplateParameterArray TParams) {
+                        unsigned VIndex, int ThisAdjustment,
+                        DIType *VTableHolder, unsigned Flags, bool isOptimized,
+                        DITemplateParameterArray TParams) {
   assert(getNonCompileUnitScope(Context) &&
          "Methods should have both a Context and a context that isn't "
          "the compile unit.");
@@ -703,7 +704,7 @@ DIBuilder::createMethod(DIScope *Context
   auto *SP = getSubprogram(
       /* IsDistinct = */ isDefinition, VMContext, cast<DIScope>(Context), Name,
       LinkageName, F, LineNo, Ty, isLocalToUnit, isDefinition, LineNo,
-      VTableHolder, VK, VIndex, Flags, isOptimized,
+      VTableHolder, VK, VIndex, ThisAdjustment, Flags, isOptimized,
       isDefinition ? CUNode : nullptr, TParams, nullptr, nullptr);
 
   if (isDefinition)

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Thu Jun 30 21:41:21 2016
@@ -412,22 +412,22 @@ DISubprogram *DISubprogram::getImpl(
     MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
     bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
     Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
-    unsigned Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams,
-    Metadata *Declaration, Metadata *Variables, StorageType Storage,
-    bool ShouldCreate) {
+    int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit,
+    Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+    StorageType Storage, bool ShouldCreate) {
   assert(isCanonical(Name) && "Expected canonical MDString");
   assert(isCanonical(LinkageName) && "Expected canonical MDString");
-  DEFINE_GETIMPL_LOOKUP(DISubprogram,
-                        (Scope, Name, LinkageName, File, Line, Type,
-                         IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
-                         Virtuality, VirtualIndex, Flags, IsOptimized, Unit,
-                         TemplateParams, Declaration, Variables));
+  DEFINE_GETIMPL_LOOKUP(
+      DISubprogram,
+      (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
+       ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment,
+       Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables));
   Metadata *Ops[] = {File,           Scope,       Name,           Name,
                      LinkageName,    Type,        ContainingType, Unit,
                      TemplateParams, Declaration, Variables};
-  DEFINE_GETIMPL_STORE(DISubprogram,
-                       (Line, ScopeLine, Virtuality, VirtualIndex, Flags,
-                        IsLocalToUnit, IsDefinition, IsOptimized),
+  DEFINE_GETIMPL_STORE(DISubprogram, (Line, ScopeLine, Virtuality, VirtualIndex,
+                                      ThisAdjustment, Flags, IsLocalToUnit,
+                                      IsDefinition, IsOptimized),
                        Ops);
 }
 

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Thu Jun 30 21:41:21 2016
@@ -528,6 +528,7 @@ template <> struct MDNodeKeyImpl<DISubpr
   Metadata *ContainingType;
   unsigned Virtuality;
   unsigned VirtualIndex;
+  int ThisAdjustment;
   unsigned Flags;
   bool IsOptimized;
   Metadata *Unit;
@@ -539,15 +540,16 @@ template <> struct MDNodeKeyImpl<DISubpr
                 Metadata *File, unsigned Line, Metadata *Type,
                 bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
                 Metadata *ContainingType, unsigned Virtuality,
-                unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-                Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration,
-                Metadata *Variables)
+                unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+                bool IsOptimized, Metadata *Unit, Metadata *TemplateParams,
+                Metadata *Declaration, Metadata *Variables)
       : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
         Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
         IsDefinition(IsDefinition), ScopeLine(ScopeLine),
         ContainingType(ContainingType), Virtuality(Virtuality),
-        VirtualIndex(VirtualIndex), Flags(Flags), IsOptimized(IsOptimized),
-        Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration),
+        VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment),
+        Flags(Flags), IsOptimized(IsOptimized), Unit(Unit),
+        TemplateParams(TemplateParams), Declaration(Declaration),
         Variables(Variables) {}
   MDNodeKeyImpl(const DISubprogram *N)
       : Scope(N->getRawScope()), Name(N->getRawName()),
@@ -556,8 +558,9 @@ template <> struct MDNodeKeyImpl<DISubpr
         IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
         ScopeLine(N->getScopeLine()), ContainingType(N->getRawContainingType()),
         Virtuality(N->getVirtuality()), VirtualIndex(N->getVirtualIndex()),
-        Flags(N->getFlags()), IsOptimized(N->isOptimized()),
-        Unit(N->getRawUnit()), TemplateParams(N->getRawTemplateParams()),
+        ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),
+        IsOptimized(N->isOptimized()), Unit(N->getRawUnit()),
+        TemplateParams(N->getRawTemplateParams()),
         Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()) {}
 
   bool isKeyOf(const DISubprogram *RHS) const {
@@ -569,8 +572,10 @@ template <> struct MDNodeKeyImpl<DISubpr
            ScopeLine == RHS->getScopeLine() &&
            ContainingType == RHS->getRawContainingType() &&
            Virtuality == RHS->getVirtuality() &&
-           VirtualIndex == RHS->getVirtualIndex() && Flags == RHS->getFlags() &&
-           IsOptimized == RHS->isOptimized() && Unit == RHS->getUnit() &&
+           VirtualIndex == RHS->getVirtualIndex() &&
+           ThisAdjustment == RHS->getThisAdjustment() &&
+           Flags == RHS->getFlags() && IsOptimized == RHS->isOptimized() &&
+           Unit == RHS->getUnit() &&
            TemplateParams == RHS->getRawTemplateParams() &&
            Declaration == RHS->getRawDeclaration() &&
            Variables == RHS->getRawVariables();

Modified: llvm/trunk/test/Assembler/disubprogram.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/disubprogram.ll?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/disubprogram.ll (original)
+++ llvm/trunk/test/Assembler/disubprogram.ll Thu Jun 30 21:41:21 2016
@@ -28,13 +28,13 @@ define void @_Z3foov() !dbg !9 {
 ; CHECK: !9 = !DISubprogram(scope: null, isLocal: false, isDefinition: false, isOptimized: false)
 !9 = !DISubprogram(isDefinition: false)
 
-; CHECK: !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, flags: DIFlagPrototyped, isOptimized: true, unit: !8, templateParams: !5, declaration: !9, variables: !6)
+; CHECK: !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, thisAdjustment: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !8, templateParams: !5, declaration: !9, variables: !6)
 !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1,
                             file: !2, line: 7, type: !3, isLocal: true,
                             isDefinition: true, scopeLine: 8,
                             containingType: !4,
                             virtuality: DW_VIRTUALITY_pure_virtual,
-                            virtualIndex: 10, flags: DIFlagPrototyped,
+                            virtualIndex: 10, thisAdjustment: 3, flags: DIFlagPrototyped,
                             isOptimized: true, unit: !8, templateParams: !5,
                             declaration: !9, variables: !6)
 

Added: llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll?rev=274325&view=auto
==============================================================================
--- llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll (added)
+++ llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll Thu Jun 30 21:41:21 2016
@@ -0,0 +1,30 @@
+; RUN: llvm-dis < %s.bc | FileCheck %s
+; RUN: verify-uselistorder < %s.bc
+
+; Test upgrading from bitcode without a this adjustment record. It will fill in
+; an implicit zero thisAdjustment, so it will not be present in the output.
+
+; CHECK: DISubprogram(name: "f",
+; CHECK-NOT: thisAdjustment
+; CHECK-SAME: ){{$}}
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.23918"
+
+; Function Attrs: nounwind uwtable
+define void @f() !dbg !7 {
+entry:
+  ret void, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocation(line: 1, column: 11, scope: !7)

Added: llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll.bc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll.bc?rev=274325&view=auto
==============================================================================
Binary files llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll.bc (added) and llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll.bc Thu Jun 30 21:41:21 2016 differ

Added: llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll?rev=274325&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll Thu Jun 30 21:41:21 2016
@@ -0,0 +1,441 @@
+; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
+
+; C++ source used to generate IR:
+; $ cat t.cpp
+; struct A {
+;   virtual int f();
+; };
+; struct B {
+;   virtual int g() = 0;
+; };
+; struct C : A, B {
+;   int c = 42;
+;   virtual int g();
+; };
+; int C::g() { return c; }
+; struct D : virtual B {
+;   int d = 13;
+;   virtual int g();
+; };
+; int D::g() { return d; }
+; $ clang t.cpp -S -emit-llvm -fstandalone-debug -g -gcodeview -o t.ll
+
+; A::f
+; CHECK:      MemberFunction ({{.*}}) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK-NEXT:   ReturnType: int (0x74)
+; CHECK-NEXT:   ClassType: A ({{.*}})
+; CHECK-NEXT:   ThisType: A* ({{.*}})
+; CHECK-NEXT:   CallingConvention: NearC (0x0)
+; CHECK-NEXT:   FunctionOptions [ (0x0)
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   NumParameters: 0
+; CHECK-NEXT:   ArgListType: () ({{.*}})
+; CHECK-NEXT:   ThisAdjustment: 0
+; CHECK-NEXT: }
+
+; A::g
+; CHECK:      MemberFunction ({{.*}}) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK-NEXT:   ReturnType: int (0x74)
+; CHECK-NEXT:   ClassType: B ({{.*}})
+; CHECK-NEXT:   ThisType: B* ({{.*}})
+; CHECK-NEXT:   CallingConvention: NearC (0x0)
+; CHECK-NEXT:   FunctionOptions [ (0x0)
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   NumParameters: 0
+; CHECK-NEXT:   ArgListType: () ({{.*}})
+; CHECK-NEXT:   ThisAdjustment: 0
+; CHECK-NEXT: }
+
+; C::g
+; CHECK:      MemberFunction ([[C_g:.*]]) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK-NEXT:   ReturnType: int (0x74)
+; CHECK-NEXT:   ClassType: C ({{.*}})
+; CHECK-NEXT:   ThisType: C* ({{.*}})
+; CHECK-NEXT:   CallingConvention: NearC (0x0)
+; CHECK-NEXT:   FunctionOptions [ (0x0)
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   NumParameters: 0
+; CHECK-NEXT:   ArgListType: () ({{.*}})
+; CHECK-NEXT:   ThisAdjustment: 8
+; CHECK-NEXT: }
+
+; CHECK:      FieldList ({{.*}}) {
+; CHECK:        OneMethod {
+; CHECK-NEXT:     AccessSpecifier: Public (0x3)
+; CHECK-NEXT:     MethodKind: Virtual (0x1)
+; CHECK-NEXT:     Type: int C::() ([[C_g]])
+; CHECK-NEXT:     Name: g
+; CHECK-NEXT:   }
+; CHECK-NEXT: }
+
+; D::g
+; CHECK:      MemberFunction ([[D_g:.*]]) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNCTION (0x1009)
+; CHECK-NEXT:   ReturnType: int (0x74)
+; CHECK-NEXT:   ClassType: D ({{.*}})
+; CHECK-NEXT:   ThisType: D* ({{.*}})
+; CHECK-NEXT:   CallingConvention: NearC (0x0)
+; CHECK-NEXT:   FunctionOptions [ (0x0)
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   NumParameters: 0
+; CHECK-NEXT:   ArgListType: () ({{.*}})
+; CHECK-NEXT:   ThisAdjustment: 16
+; CHECK-NEXT: }
+
+; CHECK:      FieldList ({{.*}}) {
+; CHECK:        OneMethod {
+; CHECK-NEXT:     AccessSpecifier: Public (0x3)
+; CHECK-NEXT:     MethodKind: Virtual (0x1)
+; CHECK-NEXT:     Type: int D::() ([[D_g]])
+; CHECK-NEXT:     Name: g
+; CHECK-NEXT:   }
+; CHECK-NEXT: }
+
+; Need to skip constructor IDs...
+; CHECK: MemberFuncId ({{.*}}) {
+; CHECK:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK:   ClassType: A
+; CHECK:   FunctionType: void A::()
+; CHECK:   Name: A
+; CHECK: }
+; CHECK: MemberFuncId ({{.*}}) {
+; CHECK:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK:   ClassType: B
+; CHECK:   FunctionType: void B::()
+; CHECK:   Name: B
+; CHECK: }
+; CHECK: MemberFuncId ({{.*}}) {
+; CHECK:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK:   ClassType: C
+; CHECK:   FunctionType: void C::()
+; CHECK:   Name: C
+; CHECK: }
+; CHECK: MemberFuncId ({{.*}}) {
+; CHECK:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK:   ClassType: D
+; CHECK:   FunctionType: void D::()
+; CHECK:   Name: D
+; CHECK: }
+
+; CHECK:      MemberFuncId ({{.*}}) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK-NEXT:   ClassType: C ({{.*}})
+; CHECK-NEXT:   FunctionType: int C::() ([[C_g]])
+; CHECK-NEXT:   Name: g
+; CHECK-NEXT: }
+
+; CHECK:      MemberFuncId ({{.*}}) {
+; CHECK-NEXT:   TypeLeafKind: LF_MFUNC_ID (0x1602)
+; CHECK-NEXT:   ClassType: D ({{.*}})
+; CHECK-NEXT:   FunctionType: int D::() ([[D_g]])
+; CHECK-NEXT:   Name: g
+; CHECK-NEXT: }
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.23918"
+
+%struct.A = type { i32 (...)** }
+%struct.B = type { i32 (...)** }
+%struct.C = type { %struct.A, %struct.B, i32 }
+%struct.D = type { i32*, i32, %struct.B }
+
+$"\01??0A@@QEAA at XZ" = comdat any
+
+$"\01??0B@@QEAA at XZ" = comdat any
+
+$"\01??0C@@QEAA at XZ" = comdat any
+
+$"\01??0D@@QEAA at XZ" = comdat any
+
+$"\01?g at C@@UEAAHXZ" = comdat any
+
+$"\01?g at D@@UEAAHXZ" = comdat any
+
+$"\01??_7A@@6B@" = comdat any
+
+$"\01??_7B@@6B@" = comdat any
+
+$"\01??_7C@@6BA@@@" = comdat any
+
+$"\01??_7C@@6BB@@@" = comdat any
+
+$"\01??_8D@@7B@" = comdat any
+
+$"\01??_7D@@6B@" = comdat any
+
+@"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.A*)* @"\01?f at A@@UEAAHXZ" to i8*)], comdat
+@"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.B*)* @"\01?g at B@@UEAAHXZ" to i8*)], comdat
+@"\01??_7C@@6BA@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.A*)* @"\01?f at A@@UEAAHXZ" to i8*)], comdat
+@"\01??_7C@@6BB@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (i8*)* @"\01?g at C@@UEAAHXZ" to i8*)], comdat
+@"\01??_8D@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16], comdat
+@"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (i8*)* @"\01?g at D@@UEAAHXZ" to i8*)], comdat
+
+; Function Attrs: uwtable
+define void @"\01?usetypes@@YAXXZ"() #0 !dbg !7 {
+entry:
+  %a = alloca %struct.A, align 8
+  %b = alloca %struct.B, align 8
+  %c = alloca %struct.C, align 8
+  %d = alloca %struct.D, align 8
+  call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !10, metadata !23), !dbg !24
+  %call = call %struct.A* @"\01??0A@@QEAA at XZ"(%struct.A* %a) #5, !dbg !24
+  call void @llvm.dbg.declare(metadata %struct.B* %b, metadata !25, metadata !23), !dbg !33
+  %call1 = call %struct.B* @"\01??0B@@QEAA at XZ"(%struct.B* %b) #5, !dbg !33
+  call void @llvm.dbg.declare(metadata %struct.C* %c, metadata !34, metadata !23), !dbg !44
+  %call2 = call %struct.C* @"\01??0C@@QEAA at XZ"(%struct.C* %c) #5, !dbg !44
+  call void @llvm.dbg.declare(metadata %struct.D* %d, metadata !45, metadata !23), !dbg !55
+  %call3 = call %struct.D* @"\01??0D@@QEAA at XZ"(%struct.D* %d, i32 1) #5, !dbg !55
+  %0 = bitcast %struct.C* %c to i8*, !dbg !56
+  %1 = getelementptr i8, i8* %0, i64 8, !dbg !56
+  %call4 = call i32 @"\01?g at C@@UEAAHXZ"(i8* %1), !dbg !56
+  ret void, !dbg !57
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: inlinehint nounwind uwtable
+define linkonce_odr %struct.A* @"\01??0A@@QEAA at XZ"(%struct.A* returned %this) unnamed_addr #2 comdat align 2 !dbg !58 {
+entry:
+  %this.addr = alloca %struct.A*, align 8
+  store %struct.A* %this, %struct.A** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !62, metadata !23), !dbg !64
+  %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+  %0 = bitcast %struct.A* %this1 to i32 (...)***, !dbg !65
+  store i32 (...)** bitcast ([1 x i8*]* @"\01??_7A@@6B@" to i32 (...)**), i32 (...)*** %0, align 8, !dbg !65
+  ret %struct.A* %this1, !dbg !65
+}
+
+; Function Attrs: inlinehint nounwind uwtable
+define linkonce_odr %struct.B* @"\01??0B@@QEAA at XZ"(%struct.B* returned %this) unnamed_addr #2 comdat align 2 !dbg !66 {
+entry:
+  %this.addr = alloca %struct.B*, align 8
+  store %struct.B* %this, %struct.B** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !70, metadata !23), !dbg !72
+  %this1 = load %struct.B*, %struct.B** %this.addr, align 8
+  %0 = bitcast %struct.B* %this1 to i32 (...)***, !dbg !73
+  store i32 (...)** bitcast ([1 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %0, align 8, !dbg !73
+  ret %struct.B* %this1, !dbg !73
+}
+
+; Function Attrs: inlinehint nounwind uwtable
+define linkonce_odr %struct.C* @"\01??0C@@QEAA at XZ"(%struct.C* returned %this) unnamed_addr #2 comdat align 2 !dbg !74 {
+entry:
+  %this.addr = alloca %struct.C*, align 8
+  store %struct.C* %this, %struct.C** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !78, metadata !23), !dbg !80
+  %this1 = load %struct.C*, %struct.C** %this.addr, align 8
+  %0 = bitcast %struct.C* %this1 to %struct.A*, !dbg !81
+  %call = call %struct.A* @"\01??0A@@QEAA at XZ"(%struct.A* %0) #5, !dbg !81
+  %1 = bitcast %struct.C* %this1 to i8*, !dbg !81
+  %2 = getelementptr inbounds i8, i8* %1, i64 8, !dbg !81
+  %3 = bitcast i8* %2 to %struct.B*, !dbg !81
+  %call2 = call %struct.B* @"\01??0B@@QEAA at XZ"(%struct.B* %3) #5, !dbg !81
+  %4 = bitcast %struct.C* %this1 to i32 (...)***, !dbg !81
+  store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@@6BA@@@" to i32 (...)**), i32 (...)*** %4, align 8, !dbg !81
+  %5 = bitcast %struct.C* %this1 to i8*, !dbg !81
+  %add.ptr = getelementptr inbounds i8, i8* %5, i64 8, !dbg !81
+  %6 = bitcast i8* %add.ptr to i32 (...)***, !dbg !81
+  store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@@6BB@@@" to i32 (...)**), i32 (...)*** %6, align 8, !dbg !81
+  %c = getelementptr inbounds %struct.C, %struct.C* %this1, i32 0, i32 2, !dbg !82
+  store i32 42, i32* %c, align 8, !dbg !82
+  ret %struct.C* %this1, !dbg !81
+}
+
+; Function Attrs: inlinehint nounwind uwtable
+define linkonce_odr %struct.D* @"\01??0D@@QEAA at XZ"(%struct.D* returned %this, i32 %is_most_derived) unnamed_addr #2 comdat align 2 !dbg !83 {
+entry:
+  %retval = alloca %struct.D*, align 8
+  %is_most_derived.addr = alloca i32, align 4
+  %this.addr = alloca %struct.D*, align 8
+  store i32 %is_most_derived, i32* %is_most_derived.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %is_most_derived.addr, metadata !87, metadata !23), !dbg !88
+  store %struct.D* %this, %struct.D** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.D** %this.addr, metadata !89, metadata !23), !dbg !88
+  %this1 = load %struct.D*, %struct.D** %this.addr, align 8
+  store %struct.D* %this1, %struct.D** %retval, align 8
+  %is_most_derived2 = load i32, i32* %is_most_derived.addr, align 4
+  %is_complete_object = icmp ne i32 %is_most_derived2, 0, !dbg !91
+  br i1 %is_complete_object, label %ctor.init_vbases, label %ctor.skip_vbases, !dbg !91
+
+ctor.init_vbases:                                 ; preds = %entry
+  %this.int8 = bitcast %struct.D* %this1 to i8*, !dbg !91
+  %0 = getelementptr inbounds i8, i8* %this.int8, i64 0, !dbg !91
+  %vbptr.D = bitcast i8* %0 to i32**, !dbg !91
+  store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@@7B@", i32 0, i32 0), i32** %vbptr.D, align 8, !dbg !91
+  %1 = bitcast %struct.D* %this1 to i8*, !dbg !91
+  %2 = getelementptr inbounds i8, i8* %1, i64 16, !dbg !91
+  %3 = bitcast i8* %2 to %struct.B*, !dbg !91
+  %call = call %struct.B* @"\01??0B@@QEAA at XZ"(%struct.B* %3) #5, !dbg !91
+  br label %ctor.skip_vbases, !dbg !91
+
+ctor.skip_vbases:                                 ; preds = %ctor.init_vbases, %entry
+  %4 = bitcast %struct.D* %this1 to i8*, !dbg !91
+  %vbptr = getelementptr inbounds i8, i8* %4, i64 0, !dbg !91
+  %5 = bitcast i8* %vbptr to i32**, !dbg !91
+  %vbtable = load i32*, i32** %5, align 8, !dbg !91
+  %6 = getelementptr inbounds i32, i32* %vbtable, i32 1, !dbg !91
+  %vbase_offs = load i32, i32* %6, align 4, !dbg !91
+  %7 = sext i32 %vbase_offs to i64, !dbg !91
+  %8 = add nsw i64 0, %7, !dbg !91
+  %9 = bitcast %struct.D* %this1 to i8*, !dbg !91
+  %add.ptr = getelementptr inbounds i8, i8* %9, i64 %8, !dbg !91
+  %10 = bitcast i8* %add.ptr to i32 (...)***, !dbg !91
+  store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@@6B@" to i32 (...)**), i32 (...)*** %10, align 8, !dbg !91
+  %d = getelementptr inbounds %struct.D, %struct.D* %this1, i32 0, i32 1, !dbg !92
+  store i32 13, i32* %d, align 8, !dbg !92
+  %11 = load %struct.D*, %struct.D** %retval, align 8, !dbg !91
+  ret %struct.D* %11, !dbg !91
+}
+
+; Function Attrs: nounwind uwtable
+define linkonce_odr i32 @"\01?g at C@@UEAAHXZ"(i8*) unnamed_addr #3 comdat align 2 !dbg !93 {
+entry:
+  %this.addr = alloca %struct.C*, align 8
+  %1 = getelementptr inbounds i8, i8* %0, i32 -8
+  %this = bitcast i8* %1 to %struct.C*
+  store %struct.C* %this, %struct.C** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !94, metadata !23), !dbg !95
+  %this1 = load %struct.C*, %struct.C** %this.addr, align 8
+  %c = getelementptr inbounds %struct.C, %struct.C* %this1, i32 0, i32 2, !dbg !96
+  %2 = load i32, i32* %c, align 8, !dbg !96
+  ret i32 %2, !dbg !97
+}
+
+declare i32 @"\01?f at A@@UEAAHXZ"(%struct.A*) unnamed_addr #4
+
+declare i32 @"\01?g at B@@UEAAHXZ"(%struct.B*) unnamed_addr #4
+
+; Function Attrs: nounwind uwtable
+define linkonce_odr i32 @"\01?g at D@@UEAAHXZ"(i8*) unnamed_addr #3 comdat align 2 !dbg !98 {
+entry:
+  %this.addr = alloca %struct.D*, align 8
+  %1 = getelementptr inbounds i8, i8* %0, i32 -16
+  %this = bitcast i8* %1 to %struct.D*
+  store %struct.D* %this, %struct.D** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata %struct.D** %this.addr, metadata !99, metadata !23), !dbg !100
+  %this1 = load %struct.D*, %struct.D** %this.addr, align 8
+  %d = getelementptr inbounds %struct.D, %struct.D* %this1, i32 0, i32 1, !dbg !101
+  %2 = load i32, i32* %d, align 8, !dbg !101
+  ret i32 %2, !dbg !102
+}
+
+attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { inlinehint nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #5 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"CodeView", i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 3.9.0 "}
+!7 = distinct !DISubprogram(name: "usetypes", linkageName: "\01?usetypes@@YAXXZ", scope: !1, file: !1, line: 15, type: !8, isLocal: false, isDefinition: true, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 16, type: !11)
+!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 64, align: 64, elements: !12, vtableHolder: !11, identifier: ".?AUA@@")
+!12 = !{!13, !19}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial)
+!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !16, size: 64)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!18}
+!18 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!19 = !DISubprogram(name: "f", linkageName: "\01?f at A@@UEAAHXZ", scope: !11, file: !1, line: 2, type: !20, isLocal: false, isDefinition: false, scopeLine: 2, containingType: !11, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, flags: DIFlagPrototyped | DIFlagIntroducedVirtual, isOptimized: false)
+!20 = !DISubroutineType(types: !21)
+!21 = !{!18, !22}
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!23 = !DIExpression()
+!24 = !DILocation(line: 16, column: 5, scope: !7)
+!25 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 17, type: !26)
+!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !1, line: 4, size: 64, align: 64, elements: !27, vtableHolder: !26, identifier: ".?AUB@@")
+!27 = !{!28, !29}
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial)
+!29 = !DISubprogram(name: "g", linkageName: "\01?g at B@@UEAAHXZ", scope: !26, file: !1, line: 5, type: !30, isLocal: false, isDefinition: false, scopeLine: 5, containingType: !26, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 0, flags: DIFlagPrototyped | DIFlagIntroducedVirtual, isOptimized: false)
+!30 = !DISubroutineType(types: !31)
+!31 = !{!18, !32}
+!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!33 = !DILocation(line: 17, column: 5, scope: !7)
+!34 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 18, type: !35)
+!35 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", file: !1, line: 7, size: 192, align: 64, elements: !36, vtableHolder: !11, identifier: ".?AUC@@")
+!36 = !{!37, !38, !39, !40}
+!37 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !35, baseType: !11)
+!38 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !35, baseType: !26, offset: 64)
+!39 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !35, file: !1, line: 8, baseType: !18, size: 32, align: 32, offset: 128)
+!40 = !DISubprogram(name: "g", linkageName: "\01?g at C@@UEAAHXZ", scope: !35, file: !1, line: 9, type: !41, isLocal: false, isDefinition: false, scopeLine: 9, containingType: !35, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, thisAdjustment: 8, flags: DIFlagPrototyped, isOptimized: false)
+!41 = !DISubroutineType(types: !42)
+!42 = !{!18, !43}
+!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!44 = !DILocation(line: 18, column: 5, scope: !7)
+!45 = !DILocalVariable(name: "d", scope: !7, file: !1, line: 19, type: !46)
+!46 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", file: !1, line: 11, size: 192, align: 64, elements: !47, vtableHolder: !46, identifier: ".?AUD@@")
+!47 = !{!48, !49, !50, !51}
+!48 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !46, baseType: !26, offset: 4, flags: DIFlagVirtual)
+!49 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$D", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial)
+!50 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !46, file: !1, line: 12, baseType: !18, size: 32, align: 32, offset: 64)
+!51 = !DISubprogram(name: "g", linkageName: "\01?g at D@@UEAAHXZ", scope: !46, file: !1, line: 13, type: !52, isLocal: false, isDefinition: false, scopeLine: 13, containingType: !46, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, thisAdjustment: 16, flags: DIFlagPrototyped, isOptimized: false)
+!52 = !DISubroutineType(types: !53)
+!53 = !{!18, !54}
+!54 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !46, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!55 = !DILocation(line: 19, column: 5, scope: !7)
+!56 = !DILocation(line: 20, column: 5, scope: !7)
+!57 = !DILocation(line: 21, column: 1, scope: !7)
+!58 = distinct !DISubprogram(name: "A", linkageName: "\01??0A@@QEAA at XZ", scope: !11, file: !1, line: 1, type: !59, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !61, variables: !2)
+!59 = !DISubroutineType(types: !60)
+!60 = !{null, !22}
+!61 = !DISubprogram(name: "A", scope: !11, type: !59, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!62 = !DILocalVariable(name: "this", arg: 1, scope: !58, type: !63, flags: DIFlagArtificial | DIFlagObjectPointer)
+!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, align: 64)
+!64 = !DILocation(line: 0, scope: !58)
+!65 = !DILocation(line: 1, column: 8, scope: !58)
+!66 = distinct !DISubprogram(name: "B", linkageName: "\01??0B@@QEAA at XZ", scope: !26, file: !1, line: 4, type: !67, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !69, variables: !2)
+!67 = !DISubroutineType(types: !68)
+!68 = !{null, !32}
+!69 = !DISubprogram(name: "B", scope: !26, type: !67, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!70 = !DILocalVariable(name: "this", arg: 1, scope: !66, type: !71, flags: DIFlagArtificial | DIFlagObjectPointer)
+!71 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64, align: 64)
+!72 = !DILocation(line: 0, scope: !66)
+!73 = !DILocation(line: 4, column: 8, scope: !66)
+!74 = distinct !DISubprogram(name: "C", linkageName: "\01??0C@@QEAA at XZ", scope: !35, file: !1, line: 7, type: !75, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !77, variables: !2)
+!75 = !DISubroutineType(types: !76)
+!76 = !{null, !43}
+!77 = !DISubprogram(name: "C", scope: !35, type: !75, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!78 = !DILocalVariable(name: "this", arg: 1, scope: !74, type: !79, flags: DIFlagArtificial | DIFlagObjectPointer)
+!79 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 64, align: 64)
+!80 = !DILocation(line: 0, scope: !74)
+!81 = !DILocation(line: 7, column: 8, scope: !74)
+!82 = !DILocation(line: 8, column: 7, scope: !74)
+!83 = distinct !DISubprogram(name: "D", linkageName: "\01??0D@@QEAA at XZ", scope: !46, file: !1, line: 11, type: !84, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !86, variables: !2)
+!84 = !DISubroutineType(types: !85)
+!85 = !{null, !54}
+!86 = !DISubprogram(name: "D", scope: !46, type: !84, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!87 = !DILocalVariable(name: "is_most_derived", arg: 2, scope: !83, type: !18, flags: DIFlagArtificial)
+!88 = !DILocation(line: 0, scope: !83)
+!89 = !DILocalVariable(name: "this", arg: 1, scope: !83, type: !90, flags: DIFlagArtificial | DIFlagObjectPointer)
+!90 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !46, size: 64, align: 64)
+!91 = !DILocation(line: 11, column: 8, scope: !83)
+!92 = !DILocation(line: 12, column: 7, scope: !83)
+!93 = distinct !DISubprogram(name: "g", linkageName: "\01?g at C@@UEAAHXZ", scope: !35, file: !1, line: 9, type: !41, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !40, variables: !2)
+!94 = !DILocalVariable(name: "this", arg: 1, scope: !93, type: !79, flags: DIFlagArtificial | DIFlagObjectPointer)
+!95 = !DILocation(line: 0, scope: !93)
+!96 = !DILocation(line: 9, column: 28, scope: !93)
+!97 = !DILocation(line: 9, column: 21, scope: !93)
+!98 = distinct !DISubprogram(name: "g", linkageName: "\01?g at D@@UEAAHXZ", scope: !46, file: !1, line: 13, type: !52, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !51, variables: !2)
+!99 = !DILocalVariable(name: "this", arg: 1, scope: !98, type: !90, flags: DIFlagArtificial | DIFlagObjectPointer)
+!100 = !DILocation(line: 0, scope: !98)
+!101 = !DILocation(line: 13, column: 28, scope: !98)
+!102 = !DILocation(line: 13, column: 21, scope: !98)

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=274325&r1=274324&r2=274325&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Thu Jun 30 21:41:21 2016
@@ -85,7 +85,7 @@ protected:
   DISubprogram *getSubprogram() {
     return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0,
                                      nullptr, false, false, 0, nullptr,
-                                     0, 0, 0, false, nullptr);
+                                     0, 0, 0, 0, false, nullptr);
   }
   DIFile *getFile() {
     return DIFile::getDistinct(Context, "file.c", "/path/to/dir");
@@ -1422,6 +1422,7 @@ TEST_F(DISubprogramTest, get) {
   DIType *ContainingType = getCompositeType();
   unsigned Virtuality = 2;
   unsigned VirtualIndex = 5;
+  int ThisAdjustment = -3;
   unsigned Flags = 6;
   unsigned NotFlags = (~Flags) & ((1 << 27) - 1);
   bool IsOptimized = false;
@@ -1430,10 +1431,11 @@ TEST_F(DISubprogramTest, get) {
   MDTuple *Variables = getTuple();
   DICompileUnit *Unit = getUnit();
 
-  auto *N = DISubprogram::get(
-      Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
-      IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags,
-      IsOptimized, Unit, TemplateParams, Declaration, Variables);
+  auto *N = DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                              Type, IsLocalToUnit, IsDefinition, ScopeLine,
+                              ContainingType, Virtuality, VirtualIndex,
+                              ThisAdjustment, Flags, IsOptimized, Unit,
+                              TemplateParams, Declaration, Variables);
 
   EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag());
   EXPECT_EQ(Scope, N->getScope());
@@ -1448,6 +1450,7 @@ TEST_F(DISubprogramTest, get) {
   EXPECT_EQ(ContainingType, N->getContainingType());
   EXPECT_EQ(Virtuality, N->getVirtuality());
   EXPECT_EQ(VirtualIndex, N->getVirtualIndex());
+  EXPECT_EQ(ThisAdjustment, N->getThisAdjustment());
   EXPECT_EQ(Flags, N->getFlags());
   EXPECT_EQ(IsOptimized, N->isOptimized());
   EXPECT_EQ(Unit, N->getUnit());
@@ -1457,99 +1460,100 @@ TEST_F(DISubprogramTest, get) {
   EXPECT_EQ(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
-
-  EXPECT_NE(N, DISubprogram::get(Context, getCompositeType(), Name, LinkageName,
-                                 File, Line, Type, IsLocalToUnit, IsDefinition,
-                                 ScopeLine, ContainingType, Virtuality,
-                                 VirtualIndex, Flags, IsOptimized, Unit,
-                                 TemplateParams, Declaration, Variables));
-  EXPECT_NE(N, DISubprogram::get(Context, Scope, "other", LinkageName, File,
-                                 Line, Type, IsLocalToUnit, IsDefinition,
-                                 ScopeLine, ContainingType, Virtuality,
-                                 VirtualIndex, Flags, IsOptimized, Unit,
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
                                  TemplateParams, Declaration, Variables));
+
+  EXPECT_NE(N, DISubprogram::get(
+                   Context, getCompositeType(), Name, LinkageName, File, Line,
+                   Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, DISubprogram::get(
+                   Context, Scope, "other", LinkageName, File, Line, Type,
+                   IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, "other", File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
-  EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, getFile(),
-                                 Line, Type, IsLocalToUnit, IsDefinition,
-                                 ScopeLine, ContainingType, Virtuality,
-                                 VirtualIndex, Flags, IsOptimized, Unit,
-                                 TemplateParams, Declaration, Variables));
-  EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File,
-                                 Line + 1, Type, IsLocalToUnit, IsDefinition,
-                                 ScopeLine, ContainingType, Virtuality,
-                                 VirtualIndex, Flags, IsOptimized, Unit,
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
                                  TemplateParams, Declaration, Variables));
-  EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
-                                 getSubroutineType(), IsLocalToUnit,
-                                 IsDefinition, ScopeLine, ContainingType,
-                                 Virtuality, VirtualIndex, Flags, IsOptimized,
-                                 Unit, TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, DISubprogram::get(
+                   Context, Scope, Name, LinkageName, getFile(), Line, Type,
+                   IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, DISubprogram::get(
+                   Context, Scope, Name, LinkageName, File, Line + 1, Type,
+                   IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams, Declaration, Variables));
+  EXPECT_NE(N,
+            DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+                              getSubroutineType(), IsLocalToUnit, IsDefinition,
+                              ScopeLine, ContainingType, Virtuality,
+                              VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                              Unit, TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, !IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, !IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
-  EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
-                                 Type, IsLocalToUnit, IsDefinition,
-                                 ScopeLine + 1, ContainingType, Virtuality,
-                                 VirtualIndex, Flags, IsOptimized, Unit,
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
                                  TemplateParams, Declaration, Variables));
+  EXPECT_NE(N, DISubprogram::get(
+                   Context, Scope, Name, LinkageName, File, Line, Type,
+                   IsLocalToUnit, IsDefinition, ScopeLine + 1, ContainingType,
+                   Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+                   Unit, TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  getCompositeType(), Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality + 1, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex + 1,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 NotFlags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, NotFlags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, !IsOptimized, Unit, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, !IsOptimized, Unit,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, nullptr, TemplateParams,
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, nullptr,
+                                 TemplateParams, Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, getTuple(),
-                                 Declaration, Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 getTuple(), Declaration, Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 getSubprogram(), Variables));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, getSubprogram(), Variables));
   EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
                                  Type, IsLocalToUnit, IsDefinition, ScopeLine,
                                  ContainingType, Virtuality, VirtualIndex,
-                                 Flags, IsOptimized, Unit, TemplateParams,
-                                 Declaration, getTuple()));
+                                 ThisAdjustment, Flags, IsOptimized, Unit,
+                                 TemplateParams, Declaration, getTuple()));
 
   TempDISubprogram Temp = N->clone();
   EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));




More information about the llvm-commits mailing list