mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-26 06:04:47 +00:00
[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:
parent
8fd475f7bc
commit
f448343ea4
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
||||
|
30
test/Bitcode/upgrade-subprogram-this.ll
Normal file
30
test/Bitcode/upgrade-subprogram-this.ll
Normal 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)
|
BIN
test/Bitcode/upgrade-subprogram-this.ll.bc
Normal file
BIN
test/Bitcode/upgrade-subprogram-this.ll.bc
Normal file
Binary file not shown.
441
test/DebugInfo/COFF/virtual-methods.ll
Normal file
441
test/DebugInfo/COFF/virtual-methods.ll
Normal 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)
|
@ -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)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user