[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

llvm-svn: 274325
This commit is contained in:
Reid Kleckner 2016-07-01 02:41:21 +00:00
parent 8fd475f7bc
commit f448343ea4
15 changed files with 669 additions and 154 deletions

View File

@ -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

View File

@ -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; }

View File

@ -3983,7 +3983,7 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
/// 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 *&Result, bool IsDistinct) {
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 *&Result, bool IsDistinct) {
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;
}

View File

@ -2466,7 +2466,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
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::parseMetadata(bool ModuleLevel) {
// 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.

View File

@ -1543,6 +1543,7 @@ void ModuleBitcodeWriter::writeDISubprogram(const DISubprogram *N,
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();

View File

@ -156,6 +156,18 @@ static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
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::getFuncIdForSubprogram(const DISubprogram *SP) {
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(DITypeRef TypeRef, DITypeRef ClassTyRef) {
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) {

View File

@ -1720,6 +1720,7 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N,
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());

View File

@ -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::createTempFunctionFwdDecl(
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, StringRef Name, StringRef LinkageName,
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)

View File

@ -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);
}

View File

@ -528,6 +528,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
Metadata *ContainingType;
unsigned Virtuality;
unsigned VirtualIndex;
int ThisAdjustment;
unsigned Flags;
bool IsOptimized;
Metadata *Unit;
@ -539,15 +540,16 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
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<DISubprogram> {
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<DISubprogram> {
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();

View File

@ -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)

View File

@ -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)

Binary file not shown.

View File

@ -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@XZ" = comdat any
$"\01??0B@@QEAA@XZ" = comdat any
$"\01??0C@@QEAA@XZ" = comdat any
$"\01??0D@@QEAA@XZ" = comdat any
$"\01?g@C@@UEAAHXZ" = comdat any
$"\01?g@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@A@@UEAAHXZ" to i8*)], comdat
@"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.B*)* @"\01?g@B@@UEAAHXZ" to i8*)], comdat
@"\01??_7C@@6BA@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.A*)* @"\01?f@A@@UEAAHXZ" to i8*)], comdat
@"\01??_7C@@6BB@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (i8*)* @"\01?g@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@A@@UEAAHXZ"(%struct.A*) unnamed_addr #4
declare i32 @"\01?g@B@@UEAAHXZ"(%struct.B*) unnamed_addr #4
; Function Attrs: nounwind uwtable
define linkonce_odr i32 @"\01?g@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@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@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@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@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@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@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@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@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@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@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)

View File

@ -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));
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, 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,
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,
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, 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)));